Docs maintenance (#316)

docs maintenance
This commit is contained in:
Jakub Chrzanowski 2020-09-21 17:15:08 +02:00 committed by GitHub
parent 5d32cbcfeb
commit 803a9d3ca8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
236 changed files with 3522 additions and 3623 deletions

1
.gitignore vendored
View File

@ -44,4 +44,3 @@ gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

View File

@ -5,5 +5,5 @@ title: Code of Conduct
## Code of Conduct
This project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct). Please make sure you read it.
This project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct).
Please make sure you read it.

View File

@ -13,9 +13,15 @@ Here are some useful things to know before authoring SDK content and submitting
## Setting Up the Documentation Build Environment
This site runs via [Jekyll](https://jekyllrb.com), which is a popular static site generator, written in Ruby. It can be hosted locally to ensure that any changes are correct. Once set up, running the site is as easy as calling `rake preview`.
This site runs via [Jekyll](https://jekyllrb.com), which is a popular static site generator, written in Ruby.
It can be hosted locally to ensure that any changes are correct.
Once set up, running the site is as easy as calling `rake preview`.
Alternatively, the site can also be hosted in a [Docker container](https://www.docker.com). On Mac and Windows, this means the site is hosted in a virtual machine. Docker maintains this container, building it based on the instructions in the [`Dockerfile`](Dockerfile). All dependencies (Ruby, etc.) are automatically installed when building the image, which reduces the manual configuration steps. The Docker image is also used to build the [published site](https://www.jetbrains.org/intellij/sdk/docs/index.html), so it is a known working environment.
Alternatively, the site can also be hosted in a [Docker container](https://www.docker.com).
On Mac and Windows, this means the site is hosted in a virtual machine.
Docker maintains this container, building it based on the instructions in the [`Dockerfile`](Dockerfile).
All dependencies (Ruby, etc.) are automatically installed when building the image, which reduces the manual configuration steps.
The Docker image is also used to build the [published site](https://www.jetbrains.org/intellij/sdk/docs/index.html), so it is a known working environment.
### Developing Documentation with Docker
@ -31,15 +37,22 @@ Follow these steps to work with Docker:
* Start the Docker container called `intellij-sdk-docs`.
* Forward port 4000 from the Docker container to port 4000 on the Docker client.
> **NOTE** For Windows and Mac, this means port 4000 of the Docker container is forwarded to port 4000 of the Docker virtual machine, not `localhost`. For Linux, the Docker client is the host machine, so `localhost:4000` is forwarded to port 4000 on the Docker container.
> **NOTE** For Windows and Mac, this means port 4000 of the Docker container is forwarded to port 4000 of the Docker virtual machine, not `localhost`.
> For Linux, the Docker client is the host machine, so `localhost:4000` is forwarded to port 4000 on the Docker container.
>
> To hit the container's port 4000 from Windows or the Mac, it is necessary to hit the IP address of the Docker client (virtual machine). Use `docker-machine ip default` to get the IP address of the Docker client. Use `X.X.X.X:4000` to hit the client in the virtual machine, which is mapped to the container's port 4000.
> To hit the container's port 4000 from Windows or the Mac, it is necessary to hit the IP address of the Docker client (virtual machine).
> Use `docker-machine ip default` to get the IP address of the Docker client.
> Use `X.X.X.X:4000` to hit the client in the virtual machine, which is mapped to the container's port 4000.
>
> Alternatively, modify the virtual machine's settings to forward port 4000 automatically to `localhost`. See this [blog post](https://acaird.github.io/computers/2014/11/16/docker-virtualbox-host-networking) for more details.
> Alternatively, modify the virtual machine's settings to forward port 4000 automatically to `localhost`.
> See this [blog post](https://acaird.github.io/computers/2014/11/16/docker-virtualbox-host-networking) for more details.
* Mount the current directory (`$PWD` is a Unix style environment variable. You can use `%CD%` on Windows, or specify the full path) as `/usr/src/app` inside the Docker container. The Docker image will see the `intellij-sdk-docs` repository as the folder `/usr/src/app`.
* Mount the current directory (`$PWD` is a Unix style environment variable.
You can use `%CD%` on Windows, or specify the full path) as `/usr/src/app` inside the Docker container.
The Docker image will see the `intellij-sdk-docs` repository as the folder `/usr/src/app`.
> **NOTE** If running on Windows in an MSYS bash script (e.g., the "Docker Quickstart Terminal"), the path to the local folder needs to be properly escaped, or the MSYS environment will translate the paths to standard Windows path, and causing an error such as `invalid value "C:\\Users\\...;C:\\Program Files\\Git\\usr\\src\\app" for flag -v`. To fix this problem, prefix the full path with double slashes, e.g., `-v //c/Users/...`, or `docker run -p 4000:4000 -v /$PWD:/usr/src/app intellij-sdk-docs` (note the leading slash before `$PWD`).
> **NOTE** If running on Windows in an MSYS bash script (e.g., the "Docker Quickstart Terminal"), the path to the local folder needs to be properly escaped, or the MSYS environment will translate the paths to standard Windows path, and causing an error such as `invalid value "C:\\Users\\...;C:\\Program Files\\Git\\usr\\src\\app" for flag -v`.
> To fix this problem, prefix the full path with double slashes, e.g., `-v //c/Users/...`, or `docker run -p 4000:4000 -v /$PWD:/usr/src/app intellij-sdk-docs` (note the leading slash before `$PWD`).
* Run the commands in the Dockerfile's `CMD` instruction to execute:
* `rake bootstrap`, which ensures all of the prerequisites are installed,
@ -52,11 +65,13 @@ To build the documentation site, you need:
* Ruby 2 - Jekyll is a Ruby application.
* Ruby 2 DevKit (for Windows) - Some of Jekyll's dependencies need to be compiled, and require the DevKit to be installed.
* `gem install bundler` - the site uses [Bundler](https://bundler.io) to manage gem dependencies within the repository, rather than globally installing to the local operating system. Run this command to install the Bundler toolset globally.
* `gem install bundler` - the site uses [Bundler](https://bundler.io) to manage gem dependencies within the repository, rather than globally installing to the local operating system.
Run this command to install the Bundler toolset globally.
#### macOS
macOS comes with Ruby already installed. The only steps required are:
macOS comes with Ruby already installed.
The only steps required are:
* `gem install bundler`
@ -73,20 +88,23 @@ This installation is easier if you use [Chocolatey](https://chocolatey.org), a p
* By default, this is `C:\tools\DevKit\config.yml`
* Add the line `- C:\tools\ruby21` (including the leading minus sign)
> **NOTE** Before running the `rake bootstrap` step listed below, please run the `devkitvars.bat` file from the DevKit. E.g. `C:\tools\DevKit\devkitvars.bat`
> **NOTE** Before running the `rake bootstrap` step listed below, please run the `devkitvars.bat` file from the DevKit.
> E.g. `C:\tools\DevKit\devkitvars.bat`
### Bootstrapping the Documentation Build Environment
1. Ensure Bundler is installed - `gem install bundler`.
2. On Windows, ensure the `devkitvars.bat` file has been run in the current command prompt (e.g., `c:\tools\DevKit\devkitvars.bat`).
3. Clone the documentation site.
4. Initialize and update the `sdkdocs-template` submodule - `git submodule init` and `git submodule update`
4. Initialize and update the `sdkdocs-template` submodule - `git submodule init` and `git submodule update`.
5. `rake bootstrap` - this uses Bundler to download all required gems.
6. `rake preview` - this will build the site, and host it in a local webserver.
### Building and Previewing the Site
To build and test the site, run `rake preview`. This will build the site and host it using the config provided. The URL of the hosted website is displayed on the screen and depends on the `baseurl` field defined in `_config.yml`.
To build and test the site, run `rake preview`.
This will build the site and host it using the config provided.
The URL of the hosted website is displayed on the screen and depends on the `baseurl` field defined in `_config.yml`.
> **NOTE** You must use `localhost` as hostname, _NOT_ 0.0.0.0, otherwise fonts fail to load.
@ -125,4 +143,3 @@ Before creating or altering content, please consult these guides:
* [SDK Code Sample Guidelines](intro/sdk_code_guidelines.md).
Conventions for code sample organization, project settings, and naming conventions are described in this document.
Always test code changes by building and testing the SDK code sample.

View File

@ -15,8 +15,7 @@ redirect_from:
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
JetBrains provides an official plugins repository [JetBrains Plugin Repository](https://plugins.jetbrains.com) for all IntelliJ Platform-based IDEs,
as well as TeamCity (limited functionality).
JetBrains provides an official plugins repository [JetBrains Plugin Repository](https://plugins.jetbrains.com) for all IntelliJ Platform-based IDEs, as well as TeamCity (limited functionality).
> **WARNING** **Part X - Plugin Repository** pages have moved to [JetBrains Marketplace](https://plugins.jetbrains.com/docs/marketplace/about-marketplace.html) documentation, please update your bookmarks.
@ -31,4 +30,3 @@ For your convenience pages previously part of this documentation are linked belo
* [Plugin Developers List](https://plugins.jetbrains.com/docs/marketplace/plugin-developers-list.html)
* [Plugin Recommendations](https://plugins.jetbrains.com/docs/marketplace/intellij-plugin-recommendations.html)
* [Custom Release Channels](https://plugins.jetbrains.com/docs/marketplace/custom-release-channels.html)

View File

@ -5,7 +5,7 @@ title: Action System
## Introduction
The actions system is an extension point that allows plugins to add their items to IntelliJ Platform-based IDE menus and toolbars.
For example, one of the action classes is responsible for the **File \| Open File...** menu item and for the **Open File** toolbar button.
For example, one of the action classes is responsible for the **File \| Open File...** menu item and the **Open File** toolbar button.
Actions in the IntelliJ Platform require a [code implementation](#action-implementation) and must be [registered](#registering-actions) with the IntelliJ Platform.
The action implementation determines the contexts in which an action is available, and its functionality when selected in the UI.
@ -23,32 +23,32 @@ The rest of this page is an overview of actions as an extension point.
An action is a class derived from the abstract class [`AnAction`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java).
The IntelliJ Platform calls methods of an action when a user interacts with a menu item or toolbar button.
> **WARNING** Classes based on `AnAction` do not have class fields of any kind. This is because an instance of `AnAction` class
exists for the entire lifetime of the application. If `AnAction` class uses a field to store data that has a shorter
lifetime and doesn't clear this data promptly, the data leaks. For example, any `AnAction` data that exists
only within the context of a `Project` causes the `Project` to be kept in memory after the user has closed it.
> **WARNING** Classes based on `AnAction` do not have class fields of any kind.
> This is because an instance of `AnAction` class exists for the entire lifetime of the application.
> If the `AnAction` class uses a field to store data that has a shorter lifetime and doesn't clear this data promptly, the data leaks.
> For example, any `AnAction` data that exists only within the context of a `Project` causes the `Project` to be kept in memory after the user has closed it.
### Principal Implementation Overrides
Every IntelliJ Platform action should override `AnAction.update()` and must override `AnAction.actionPerformed()`.
* An action's method `AnAction.update()` is called by the IntelliJ Platform framework to update the state of an action.
* An action's method `AnAction.update()` is called by the IntelliJ Platform framework to update an action state.
The state (enabled, visible) of an action determines whether the action is available in the UI of an IDE.
An object of type [`AnActionEvent`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java) is passed to this method, and it contains the information about the current context for the action.
An object of the [`AnActionEvent`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java) type is passed to this method and contains information about the current context for the action.
Actions are made available by changing state in the [Presentation](upsource:///platform/platform-api/src/com/intellij/ide/presentation/Presentation.java) object associated with the event context.
As explained in [Overriding the `AnAction.update()` Method](#overriding-the-anactionupdate-method), it is vital `update()` methods _execute quickly_ and return execution to the IntelliJ Platform.
* An action's method `AnAction.actionPerformed()` is called by the IntelliJ Platform if it is available and selected by the user.
* An action's method `AnAction.actionPerformed()` is called by the IntelliJ Platform if available and selected by the user.
This method does the heavy lifting for the action - it contains the code executed when the action gets invoked.
The `actionPerformed()` method also receives `AnActionEvent` as a parameter, which is used to access projects, files, selection, etc.
See [Overriding the `AnAction.actionPerformed()` Method](#overriding-the-anactionactionperformed-method) for more information.
There are other methods to override in the `AnAction` class, such as for changing the default `Presentation` object for the action.
There is also a use case for overriding action constructors when registering them with dynamic action groups, which is demonstrated in the [Grouping Actions](/tutorials/action_system/grouping_action.md#adding-child-actions-to-the-dynamic-group) tutorial.
There are other methods to override in the `AnAction` class, such as changing the default `Presentation` object for the action.
There is also a use case for overriding action constructors when registering them with dynamic action groups, demonstrated in the [Grouping Actions](/tutorials/action_system/grouping_action.md#adding-child-actions-to-the-dynamic-group) tutorial.
However, the `update()` and `actionPerformed()` methods are essential to basic operation.
### Overriding the AnAction.update Method
The method `AnAction.update()` is periodically called by the IntelliJ Platform in response to user gestures.
The `update()` method gives an action to evaluate the current context and enable or disable its functionality.
> **WARNING** The `AnAction.update()` method can be called frequently, and on a UI thread.
> **WARNING** The `AnAction.update()` method can be called frequently and on a UI thread.
This method needs to _execute very quickly_; no real work should be performed in this method.
For example, checking selection in a tree or a list is considered valid, but working with the file system is not.
@ -56,7 +56,7 @@ For example, checking selection in a tree or a list is considered valid, but wor
#### Determining the Action Context
The `AnActionEvent` object passed to `update()` carries information about the current context for the action.
Context information is available from the methods of `AnActionEvent`, providing information such as the Presentation, and whether the action is triggered from a Toolbar.
Context information is available from the methods of `AnActionEvent`, providing information such as the Presentation and whether the action is triggered by a Toolbar.
Additional context information is available using the method `AnActionEvent.getData()`.
Keys defined in [`CommonDataKeys`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/CommonDataKeys.java) are passed to the `getData()` method to retrieve objects such as `Project`, `Editor`, `PsiFile`, and other information.
Accessing this information is relatively light-weight and is suited for `AnAction.update()`.
@ -67,7 +67,7 @@ An action's enable/disable state and visibility are set using methods of the `Pr
The default `Presentation` object is a set of descriptive information about a menu or toolbar action.
Every context for an action - it might appear in multiple menus, toolbars, or Navigation search locations - has a unique presentation.
Attributes such as an action's text, description, and icons, as well as visibility and enable/disable state, are stored in the presentation.
Attributes such as an action's text, description, and icons and visibility and enable/disable state, are stored in the presentation.
The attributes in a presentation get initialized from the [action registration](#registering-actions).
However, some can be changed at runtime using the methods of the `Presentation` object associated with an action.
@ -79,8 +79,8 @@ A toolbar action displays its enabled (or selected) icon, depending on the user
When an action is disabled `AnAction.actionPerformed()` will not be called.
Toolbar actions display their respective icons for the disabled state.
The visibility of a disabled action in a menu depends on whether the host menu (e.g. "ToolsMenu") containing the action has the `compact` attribute set.
See [Grouping Actions](#grouping-actions) for more information about the `compact` attribute, and the visibility of menu actions.
The visibility of a disabled action in a menu depends on whether the host menu (e.g., "ToolsMenu") containing the action has the `compact` attribute set.
See [Grouping Actions](#grouping-actions) for more information about the `compact` attribute and menu actions' visibility.
> **NOTE** If an action is added to a toolbar, its `update()` can be called if there was any user activity or focus transfer.
If the action's availability changes in the absence of these events, then call [`ActivityTracker.getInstance().inc()`](upsource:///platform/platform-api/src/com/intellij/ide/ActivityTracker.java) to notify the action subsystem to update all toolbar actions.
@ -91,7 +91,7 @@ An example of enabling a menu action based on whether a project is open is demon
When the user selects an enabled action, be it from a menu or toolbar, the action's `AnAction.actionPerformed()` method is called.
This method contains the code executed to perform the action, and it is here that the real work gets done.
Using the `AnActionEvent` methods and `CommonDataKeys`, objects such as the `Project`, `Editor`, `PsiFile`, and other information is available.
By using the `AnActionEvent` methods and `CommonDataKeys`, objects such as the `Project`, `Editor`, `PsiFile`, and other information is available.
For example, the `actionPerformed()` method can modify, remove, or add PSI elements to a file open in the editor.
The code that executes in the `AnAction.actionPerformed()` method should execute efficiently, but it does not have to meet the same stringent requirements as the `update()` method.
@ -103,7 +103,8 @@ An example of inspecting PSI elements is demonstrated in the SDK code sample `ac
### Action IDs
Every action and action group has a unique identifier.
Basing the identifier for a custom action on the FQN of the implementation is the best practice, assuming the package incorporates the `<id>` of the plugin.
An action must have a unique identifier for each place it is used in the IDE UI, even though the FQN of the implementation is the same.
An action must have a unique identifier for each place.
It is used in the IDE UI, even though the FQN of the implementation is the same.
Definitions of identifiers for the standard IntelliJ Platform actions are in [`IdeActions`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java).
### Grouping Actions
@ -111,15 +112,15 @@ Groups organize actions into logical UI structures, which in turn can contain ot
A group of actions can form a toolbar or a menu.
Subgroups of a group can form submenus of a menu.
Actions can be included in multiple groups, and thus appear in multiple places within the IDE UI.
Actions can be included in multiple groups, and thus appear in different places within the IDE UI.
An action must have a unique identifier for each place it appears in the IDE UI.
See the [Action Declaration Reference](#action-declaration-reference) section for information about how to specify locations in the IDE UI.
<!-- TODO: Reconcile ActionPlaces vs. PlatformActions -->
#### Presentation
For every place where the action appears, a new [`Presentation`](upsource:///platform/platform-api/src/com/intellij/ide/presentation/Presentation.java) is created.
Therefore the same action can have different text or icons when it appears in different places of the user interface.
A new [`Presentation`](upsource:///platform/platform-api/src/com/intellij/ide/presentation/Presentation.java) gets created for every place where the action appears.
Therefore, the same action can have different text or icons when it appears in different places of the user interface.
Different presentations for the action are created by copying the Presentation returned by the `AnAction.getTemplatePresentation()` method.
#### Compact Attribute
@ -141,16 +142,16 @@ All other combinations of `compact`, visibility, and enablement produce N/A for
See the [Grouping Actions](/tutorials/action_system/grouping_action.md) tutorial for examples of creating action groups.
## Registering Actions
There are two main ways to register an action: either by listing it in the `<actions>` section of a plugin's `plugin.xml` file, or through code.
There are two main ways to register an action: either by listing it in the `<actions>` section of a plugin's `plugin.xml` file or through code.
### Registering Actions in plugin.xml
Registering actions in `plugin.xml` is demonstrated in the following reference examples, which document all elements and attributes that can be used in the `<actions>` section, and describes the meaning of each element.
Registering actions in `plugin.xml` is demonstrated in the following reference examples, which document all elements and attributes used in the `<actions>` section and describe each element's meaning.
#### Setting the Override-Text Element for an Action
> **TIP** Beginning in 2020.1, an alternate version of an action's menu text can be declared for use depending on where an action appears.
By using the `<override-text>` element introduced in 2020.1 of the IntelliJ Platform, the menu text for an action can be different depending on context: menu location, toolbar, etc.
Using the `<override-text>` element introduced in 2020.1 of the IntelliJ Platform, the menu text for an action can be different depending on context: menu location, toolbar, etc.
In the `action` element reference example (below) with `id` attribute `VssIntegration.GarbageCollection`, the default is to use the menu text "Garbage Collector: Collect _Garbage."
The `add-to-group` element declares the action is added to the Tools Menu.
@ -160,7 +161,7 @@ The Tools Menu is part of the Main Menu, so the displayed menu text is "Collect
A different context, such as searching for the action using **Help \| Find Action...**, displays the default text "Garbage Collector: Collect _Garbage" to give the user additional information about the action.
A second `override-text` element uses `place` and `use-text-of-place` attributes to declare the same version of the text used in the Main Menu is also used in the Editor Popup Menu.
Additional `override-text` elements could be used to specify additional places where the Main Menu text should be used.
Additional `override-text` elements could be used to specify other places where the Main Menu text should be used.
An example of using `<override-text>` is demonstrated in the [Creating Actions](/tutorials/action_system/working_with_custom_actions.md#using-override-text-for-an-action) tutorial.
@ -234,7 +235,7 @@ This, and additional information can also be found by using the [Code Completion
to which the action is added.
The group must be implemented by an instance of the DefaultActionGroup class.
The mandatory "anchor" attribute specifies the position of the
action in the group relative to other actions. It can have the values
action in the relative to other actions. It can have the values
"first", "last", "before" and "after".
The "relative-to-action" attribute is mandatory if the anchor
is set to "before" and "after", and specifies the action before or after which
@ -326,5 +327,5 @@ If a plugin needs to include a toolbar or popup menu built from a group of actio
These objects can be created through calls to the `ActionManager.createActionPopupMenu()` and `createActionToolbar()` methods.
To get a Swing component from such an object, call the respective `getComponent()` method.
If an action toolbar is attached to a specific component (for example, a panel in a tool window), call `ActionToolbar.setTargetComponent()` and pass the instance of the related component as a parameter.
Setting the target ensures that the state of the toolbar buttons depends on the state of the related component, and not on the current focus location within the IDE frame.
If an action toolbar is attached to a specific component (for example, a panel in a tool window), call `ActionToolbar.setTargetComponent()` and pass the related component's instance as a parameter.
Setting the target ensures that the toolbar buttons' state depends on the state of the related component, not on the current focus location within the IDE frame.

View File

@ -21,11 +21,11 @@ From a PSI file
## What can I do with a Document?
You may perform any operations that access or modify the file contents on "plain text" level (as a sequence of characters, not as a tree of PSI elements).
You may perform any operations that access or modify the file contents on the "plain text" level (as a sequence of characters, not as a tree of PSI elements).
## Where does a Document come from?
Document instances are created when some operation needs to access the text contents of a file (in particular, this is needed to build the PSI for a file).
Document instances are created when some operation needs to access the text contents of a file (in particular, this is necessary to build the PSI for a file).
Also, document instances not linked to any virtual files can be created temporarily, for example, representing the contents of a text editor field in a dialog.
## How long does a Document persist?
@ -48,7 +48,8 @@ To create a `Document` instance that isn't bound to anything, use `EditorFactory
## What are the rules of working with Documents?
The general read/write action rules are in effect. In addition to that, any operations which modify the contents of the document must be wrapped in a command (`CommandProcessor.getInstance().executeCommand()`).
The general read/write action rules are in effect.
Besides, any operations which modify the contents of the document must be wrapped in a command (`CommandProcessor.getInstance().executeCommand()`).
`executeCommand()` calls can be nested, and the outermost `executeCommand()` call is added to the undo stack.
If multiple documents are modified within a command, undoing this command will, by default, show a confirmation dialog to the user.
@ -60,4 +61,5 @@ All text strings passed to `Document` modification methods (`setText()`, `insert
## Are there any utilities available for working with Documents?
[`DocumentUtil`](upsource:///platform/core-impl/src/com/intellij/util/DocumentUtil.java) contains utility methods for `Document` processing.
This allows you to get information like the text offsets of particular lines. This is particularly useful when you need text location/offset information about a given `PsiElement`.
This allows you to get information like the text offsets of particular lines.
This is particularly useful when you need text location/offset information about a given `PsiElement`.

View File

@ -7,9 +7,9 @@ A file view provider ([`FileViewProvider`](upsource:///platform/core-api/src/com
For example, a JSPX page has a separate PSI tree for the Java code in it (`PsiJavaFile`), a separate tree for the XML code (`XmlFile`), and a separate tree for JSP as a whole ([`JspFile`](upsource:///java/jsp-openapi/src/com/intellij/psi/jsp/JspFile.java)).
Each of the PSI trees covers the entire contents of the file, and contains special "outer language elements" in the places where contents in a different language can be found.
Each of the PSI trees covers the entire contents of the file and contains special "outer language elements" in the places where contents in a different language can be found.
A `FileViewProvider` instance corresponds to a single `VirtualFile`, a single `Document`, and can be used to retrieve multiple `PsiFile` instances.
A `FileViewProvider` instance corresponds to a single `VirtualFile`, a single `Document`, and can retrieve multiple `PsiFile` instances.
## How do I get a FileViewProvider?
@ -19,7 +19,8 @@ A `FileViewProvider` instance corresponds to a single `VirtualFile`, a single `D
## What can I do with a FileViewProvider?
* To get the set of all languages for which PSI trees exist in a file: `fileViewProvider.getLanguages()`
* To get the PSI tree for a particular language: `fileViewProvider.getPsi(language)`. For example, to get the PSI tree for XML, use `fileViewProvider.getPsi(XMLLanguage.INSTANCE)`.
* To get the PSI tree for a particular language: `fileViewProvider.getPsi(language)`.
For example, to get the PSI tree for XML, use `fileViewProvider.getPsi(XMLLanguage.INSTANCE)`.
* To find an element of a particular language at the specified offset in the file: `fileViewProvider.findElementAt(offset, language)`
## How do I extend the FileViewProvider?

View File

@ -16,7 +16,7 @@ You must not access the model outside a read or write action for the following s
Reading data from the UI thread does not require any special effort.
However, read operations performed from any other thread need to be wrapped in a read action by using `ApplicationManager.getApplication().runReadAction()` or, shorter, [`ReadAction`](upsource:///platform/core-api/src/com/intellij/openapi/application/ReadAction.java) `run()`/`compute()`.
The corresponding objects are not guaranteed to survive between several consecutive read actions.
As a rule of thumb, whenever starting a read action, check if PSI/VFS/project/module is still valid.
As a rule of thumb, whenever starting a read action, check if the PSI/VFS/project/module is still valid.
**Writing** data is only allowed from the UI thread, and write operations always need to be wrapped in a write action with `ApplicationManager.getApplication().runWriteAction()` or, shorter, [`WriteAction`](upsource:///platform/core-api/src/com/intellij/openapi/application/WriteAction.java) `run()`/`compute()`.
Modifying the model is only allowed from write-safe contexts, including user actions and `invokeLater()` calls from them (see the next section).
@ -29,13 +29,13 @@ To pass control from a background thread to the event dispatch thread, instead o
The latter API allows specifying the _modality state_ ([`ModalityState`](upsource:///platform/core-api/src/com/intellij/openapi/application/ModalityState.java)) for the call, i.e., the stack of modal dialogs under which the call is allowed to execute:
`ModalityState.NON_MODAL`
: The operation will be executed after all modal dialogs are closed. Note that if any of the open (unrelated) project displays a per-project modal dialog, the action will be executed after the dialog is closed.
: The operation will be executed after all modal dialogs are closed. If any of the open (unrelated) project displays a per-project modal dialog, the action will be performed after the dialog is closed.
`ModalityState.stateForComponent()`
: The operation can be executed when the topmost shown dialog is the one that contains the specified component or is one of its parent dialogs.
None specified
: `ModalityState.defaultModalityState()` will be used. In most cases, this is the optimal choice, that uses current modality state when invoked from UI thread, and has special handling for background processes started with `ProgressManager`: `invokeLater()` from such a process may run in the same dialog that the process started.
: `ModalityState.defaultModalityState()` will be used. This is the optimal choice in most cases that uses the current modality state when invoked from UI thread. It has special handling for background processes started with `ProgressManager`: `invokeLater()` from such a process may run in the same dialog that the process started.
`ModalityState.any()`
: The operation will be executed as soon as possible regardless of modal dialogs. Please note that modifying PSI, VFS, or project model is prohibited from such runnables.
@ -46,39 +46,35 @@ That way, it is run after all possible indexing processes have been completed.
## Background processes and `ProcessCanceledException`
Background progresses are managed by [`ProgressManager`](upsource:///platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java) class,
which has plenty of methods to execute the given code with a modal (dialog), non-modal (visible in the status bar), or invisible progress.
Background progresses are managed by [`ProgressManager`](upsource:///platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java) class, which has plenty of methods to execute the given code with a modal (dialog), non-modal (visible in the status bar), or invisible progress.
In all cases, the code is executed on a background thread, which is associated with a [`ProgressIndicator`](upsource:///platform/core-api/src/com/intellij/openapi/progress/ProgressIndicator.java) object.
The current thread's indicator can be retrieved any time via `ProgressIndicatorProvider.getGlobalProgressIndicator()`.
For visible progresses, threads can use `ProgressIndicator` to notify the user about current status:
e.g., set text or visible fraction of the work done.
For visible progresses, threads can use `ProgressIndicator` to notify the user about current status: e.g., set text or visual fraction of the work done.
Progress indicators also provide means to handle cancellation of background processes, either by the user (pressing _Cancel_ button)
or from code (e.g., when the current operation becomes obsolete due to some changes in the project).
Progress indicators also provide means to handle cancellation of background processes, either by the user (pressing the _Cancel_ button) or from code (e.g., when the current operation becomes obsolete due to some changes in the project).
The progress can be marked as canceled by calling `ProgressIndicator.cancel()`.
The process reacts to this by calling `ProgressIndicator.checkCanceled()` (or `ProgressManager.checkCanceled()` if no indicator instance at hand).
This call throws a special unchecked [`ProcessCanceledException`](upsource:///platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java) if the background process has been canceled.
All code working with PSI, or in other kinds of background processes, must be prepared for [`ProcessCanceledException`](upsource:///platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java) being thrown from any point.
This exception should never be logged, but rethrown, and it'll be handled in the infrastructure that started the process.
This exception should never be logged but rethrown, and it'll be handled in the infrastructure that started the process.
The `checkCanceled()` should be called often enough to guarantee smooth cancellation of the process.
The `checkCanceled()` should be called often enough to guarantee the process's smooth cancellation.
PSI internals have a lot of `checkCanceled()` calls inside.
If a process does lengthy non-PSI activity, insert explicit `checkCanceled()` calls so that it happens frequently, e.g., on each _Nth_ loop iteration.
## Read Action Cancellability
Background threads shouldn't take plain read actions for a long time. The reason is that if the UI thread needs a write action (e.g., the user types something),
it must be acquired as soon as possible. Otherwise, the UI will freeze until all background threads have released their read actions.
Background threads shouldn't take plain read actions for a long time.
The reason is that if the UI thread needs a write action (e.g., the user types something), it must be acquired as soon as possible.
Otherwise, the UI will freeze until all background threads have released their read actions.
The best-known approach is to cancel background read actions whenever there's a write action about to occur, and restart that background read action later from scratch.
Editor highlighting, code completion, Goto Class/File/... actions all work like this.
To achieve that, the lengthy background operation is started with a `ProgressIndicator`, and a dedicated listener
cancels that indicator when write action is started.
The next time the background thread calls `checkCanceled()`, a `ProcessCanceledException` is thrown,
and the thread should stop its operation (and finish the read action) as soon as possible.
To achieve that, the lengthy background operation is started with a `ProgressIndicator`, and a dedicated listener cancels that indicator when write action is initiated.
The next time the background thread calls `checkCanceled()`, a `ProcessCanceledException` is thrown, and the thread should stop its operation (and finish the read action) as soon as possible.
There are two recommended ways of doing this:

View File

@ -3,44 +3,33 @@ title: Modifying the PSI
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
The PSI is a read-write representation of the source code as a tree of elements corresponding to the structure of a source
file. You can modify the PSI by *adding*, *replacing*, and *deleting* PSI elements.
The PSI is a read-write representation of the source code as a tree of elements corresponding to a source file's structure.
You can modify the PSI by *adding*, *replacing*, and *deleting* PSI elements.
To perform these operations, you use methods such as `PsiElement.add()`, `PsiElement.delete()`, and `PsiElement.replace()`,
as well as other methods defined in the `PsiElement` interface that let you process multiple elements in a single
operation, or to specify the exact location in the tree where an element needs to be added.
Just as document operations, PSI modifications need to be wrapped in a write action and in a command (and therefore
can only be performed in the event dispatch thread). See [the Documents article](documents.md#what-are-the-rules-of-working-with-documents)
for more information on commands and write actions.
To perform these operations, you use methods such as `PsiElement.add()`, `PsiElement.delete()`, and `PsiElement.replace()`, as well as other methods defined in the `PsiElement` interface that let you process multiple elements in a single operation, or to specify the exact location in the tree where an element needs to be added.
Like document operations, PSI modifications need to be wrapped in a write action and in command (and can only be performed in the event dispatch thread).
See [the Documents article](documents.md#what-are-the-rules-of-working-with-documents) for more information on commands and write actions.
## Creating the New PSI
The PSI elements to add to the tree, or to replace existing PSI elements, are normally *created from text*.
In the most general case, you use the `createFileFromText()` method of [`PsiFileFactory`](upsource:///platform/core-api/src/com/intellij/psi/PsiFileFactory.java)
to create a new file that contains the code construct which you need to add to the tree or to use as a replacement
for an existing element, traverse the resulting tree to locate the specific element that you need, and then pass that
element to `add()` or `replace()`.
The PSI elements to add to the tree or replace existing PSI elements are usually *created from text*.
In the most general case, you use the `createFileFromText()` method of [`PsiFileFactory`](upsource:///platform/core-api/src/com/intellij/psi/PsiFileFactory.java) to create a new file that contains the code construct which you need to add to the tree or to use as a replacement for an existing element, traverse the resulting tree to locate the specific part that you need, and then pass that element to `add()` or `replace()`.
Most languages provide factory methods which let you create specific code constructs more easily. For example,
the [`PsiJavaParserFacade`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiJavaParserFacade.java) class
contains methods such as `createMethodFromText()`, which creates a Java method from the given text.
Most languages provide factory methods that let you create specific code constructs more easily.
For example, the [`PsiJavaParserFacade`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiJavaParserFacade.java) class contains methods such as `createMethodFromText()`, which creates a Java method from the given text.
When you're implementing refactorings, intentions or inspection quickfixes that work with existing code, the text that
you pass to the various `createFromText()` methods will combine hard-coded fragments and fragments of code taken from
the existing file. For small code fragments (individual identifiers), you can simply append the text from the existing
code to the text of the code fragment you're building. In that case, you need to make sure that the resulting text is
syntactically correct, otherwise the `createFromText()` method will throw an exception.
When you're implementing refactorings, intentions, or inspection quickfixes that work with existing code, the text that you pass to the various `createFromText()` methods will combine hard-coded fragments and fragments of code taken from the existing file.
For small code fragments (individual identifiers), you can simply append the text from the existing code to the text of the code fragment you're building.
In that case, you need to make sure that the resulting text is syntactically correct. Otherwise the `createFromText()` method will throw an exception.
For larger code fragments, it's best to perform the modification in several steps:
* create a replacement tree fragment from text, leaving placeholders for the user code fragments;
* create a replacement tree fragment from the text, leaving placeholders for the user code fragments;
* replace the placeholders with the user code fragments;
* replace the element in the original source file with the replacement tree.
This ensures that the formatting of the user code is preserved and that the modification doesn't introduce any unwanted
whitespace changes.
This ensures that the user code's formatting is preserved and that the modification doesn't introduce any unwanted whitespace changes.
As an example of this approach, see the quickfix in the `ComparingReferencesInspection` example:
@ -64,44 +53,33 @@ equalsCall.getArgumentList().getExpressions()[0].replace(rExpr);
PsiExpression result = (PsiExpression) binaryExpression.replace(equalsCall);
```
Just as everywhere else in the IntelliJ Platform API, the text passed to `createFileFromText()` and other `createFromText()`
methods must use only `\n` as line separators.
Just as everywhere else in the IntelliJ Platform API, the text passed to `createFileFromText()` and other `createFromText()` methods must use only `\n` as line separators.
## Maintaining Tree Structure Consistency
The PSI modification methods do not restrict you in the way you can build the resulting tree structure. For example,
when working with a Java class, you can add a `for` statement as a direct child of a `PsiMethod` element, even though
the Java parser will never produce such a structure (the `for` statement will always be a child of the `PsiCodeBlock`)
representing the method body). Modifications that produce incorrect tree structures may appear to work, but they will
lead to problems and exceptions later. Therefore, you always need to ensure that the structure you built with PSI
modification operations is the same as what the parser would produce when parsing the code that you've built.
The PSI modification methods do not restrict you in the way you can build the resulting tree structure.
For example, when working with a Java class, you can add a `for` statement as a direct child of a `PsiMethod` element, even though the Java parser will never produce such a structure (the `for` statement will always be a child of the `PsiCodeBlock`) representing the method body).
Modifications that produce incorrect tree structures may appear to work, but they will lead to problems and exceptions later.
Therefore, you always need to ensure that the structure you built with PSI modification operations is the same as what the parser would produce when parsing the code that you've created.
To make sure you're not introducing inconsistencies, you can call `PsiTestUtil.checkFileStructure()` in the tests for
your action that modifies the PSI. This method ensures that the structure you've built is the same as what the parser produces.
To make sure you're not introducing inconsistencies, you can call `PsiTestUtil.checkFileStructure()` in the tests for your action that modifies the PSI.
This method ensures that the structure you've built is the same as what the parser produces.
## Whitespaces and Imports
When working with PSI modification functions, you should never create individual whitespace nodes (spaces or line breaks)
from text. Instead, all whitespace modifications are performed by the formatter, which follows the code style settings
selected by the user. Formatting is automatically performed at the end of every command, and if you need, you can
also perform it manually using the `reformat(PsiElement)` method in the
[`CodeStyleManager`](upsource:///platform/core-api/src/com/intellij/psi/codeStyle/CodeStyleManager.java) class.
When working with PSI modification functions, you should never create individual whitespace nodes (spaces or line breaks) from the text.
Instead, all whitespace modifications are performed by the formatter, which follows the code style settings selected by the user.
Formatting is automatically performed at the end of every command, and if you need, you can also perform it manually using the `reformat(PsiElement)` method in the [`CodeStyleManager`](upsource:///platform/core-api/src/com/intellij/psi/codeStyle/CodeStyleManager.java) class.
Also, when working with Java code (or with code in other languages with a similar import mechanism such as Groovy or Python),
you should never create imports manually. Instead, you should insert fully-qualified names into the code you're
generating, and then call the `shortenClassReferences()` method in the
[`JavaCodeStyleManager`](upsource:///java/java-psi-api/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java)
(or the equivalent API for the language you're working with). This ensures that the imports are created according to
the user's code style settings and inserted into the correct place of the file.
Also, when working with Java code (or with code in other languages with a similar import mechanism such as Groovy or Python), you should never create imports manually.
Instead, you should insert fully-qualified names into the code you're generating, and then call the `shortenClassReferences()` method in the [`JavaCodeStyleManager`](upsource:///java/java-psi-api/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java) (or the equivalent API for the language you're working with).
This ensures that the imports are created according to the user's code style settings and inserted into the file's correct place.
## Combining PSI and Document Modifications
In some cases, you need to perform a PSI modification and then to perform an operation on the document you've just
modified through the PSI (for example, start a live template). In this case, you need to call a special method that
completes the PSI-based post-processing (such as formatting) and commits the changes to the document. The method
you need to call is called `doPostponedOperationsAndUnblockDocument()`, and it's defined in the
[`PsiDocumentManager`](upsource:///platform/core-api/src/com/intellij/psi/PsiDocumentManager.java) class.
In some cases, you need to perform a PSI modification and then to perform an operation on the document you've just modified through the PSI (for example, start a live template).
In this case, you need to call a special method that completes the PSI-based post-processing (such as formatting) and commits the changes to the document.
The method you need to call is called `doPostponedOperationsAndUnblockDocument()`, and it's defined in the [`PsiDocumentManager`](upsource:///platform/core-api/src/com/intellij/psi/PsiDocumentManager.java) class.

View File

@ -3,24 +3,20 @@ title: Navigating the PSI
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
There are three main ways to navigate the PSI: *top-down*, *bottom-up*, and using *references*. In the first scenario,
you have a PSI file or another higher-level element (for example, a method), and you need to find all elements that match a
specified condition (for example, all variable declarations). In the second scenario, you have a specific point
in the PSI tree (for example, the element at caret) and need to find out something about its context (for example,
the element in which it has been declared). Finally, *references* allow you to navigate from the use of an element
(e.g., a method call) to the declaration (the method being called) and back. References are described in a
[separate topic](psi_references.md).
There are three main ways to navigate the PSI: *top-down*, *bottom-up*, and *references*.
In the first scenario, you have a PSI file or another higher-level element (for example, a method). You need to find all elements that match a specified condition (for example, all variable declarations).
In the second scenario, you have a specific point in the PSI tree (for example, the element at caret) and need to find out something about its context (for example, the element in which it has been declared).
Finally, *references* allow you to navigate from the usages of an element (e.g., a method call) to the declaration (the method being called) and back.
References are described in a [separate topic](psi_references.md).
## Top-Down Navigation
The most common way to perform top-down navigation is to use a *visitor*. To use a visitor, you create a class
(usually an anonymous inner class) that extends the base visitor class, override the methods that handle the elements
you're interested in, and pass the visitor instance it to `PsiElement.accept()`.
The most common way to perform top-down navigation is to use a *visitor*.
To use a visitor, you create a class (usually an anonymous inner class) that extends the base visitor class, overrides the methods that handle the elements you're interested in, and passes the visitor instance to `PsiElement.accept()`.
The base classes for visitors are language-specific. For example, if you need to process elements in a Java file,
you extend `JavaRecursiveElementVisitor` and override the methods corresponding to the Java element types you're
interested in.
The base classes for visitors are language-specific.
For example, if you need to process elements in a Java file, you extend `JavaRecursiveElementVisitor` and override the methods corresponding to the Java element types you're interested in.
The following snippet shows the use of a visitor to find all Java local variable declarations:
@ -34,26 +30,23 @@ file.accept(new JavaRecursiveElementVisitor() {
});
```
In many cases, you can also use more specific APIs for top-down navigation. For example, if you need to get a list of
all methods in a Java class, you can do that using a visitor, but a much easier way to do that is to call `PsiClass.getMethods()`.
In many cases, you can also use more specific APIs for top-down navigation.
For example, if you need to get a list of all methods in a Java class, you can use a visitor, but a much easier way to do that is calling `PsiClass.getMethods()`.
[`PsiTreeUtil`](upsource:///platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java) contains a number of
general-purpose, language-independent functions for PSI tree navigation, some of which (for example, `findChildrenOfType()`)
perform top-down navigation.
[`PsiTreeUtil`](upsource:///platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java) contains a number of general-purpose, language-independent functions for PSI tree navigation, some of which (for example, `findChildrenOfType()`) perform top-down navigation.
## Bottom-Up Navigation
The starting point for bottom-up navigation is either a specific element in the PSI tree (for example, the result of
resolving a reference), or an offset. If you have an offset, you can find the corresponding PSI element by calling
`PsiFile.findElementAt()`. This method returns the element at the lowest level of the tree (for example, an identifier),
and you need to navigate the tree up if you want to determine the broader context.
The starting point for bottom-up navigation is either a specific element in the PSI tree (for example, the result of resolving a reference) or an offset.
If you have an offset, you can find the corresponding PSI element by calling `PsiFile.findElementAt()`.
This method returns the element at the lowest level of the tree (for example, an identifier), and you need to navigate the tree up if you want to determine the broader context.
In most cases, bottom-up navigation is performed by calling `PsiTreeUtil.getParentOfType()`. This method goes up the
tree until it finds the element of the type you've specified. For example, to find the containing method, you call
`PsiTreeUtil.getParentOfType(element, PsiMethod.class)`.
In most cases, bottom-up navigation is performed by calling `PsiTreeUtil.getParentOfType()`.
This method goes up the tree until it finds the element of the type you've specified.
For example, to find the containing method, you call `PsiTreeUtil.getParentOfType(element, PsiMethod.class)`.
In some cases, you can also use specific navigation methods. For example, to find the class where a method is contained,
you call `PsiMethod.getContainingClass()`.
In some cases, you can also use specific navigation methods.
For example, to find the class where a method is contained, you call `PsiMethod.getContainingClass()`.
The following snippet shows how these calls can be used together:
@ -64,5 +57,4 @@ PsiMethod containingMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.clas
PsiClass containingClass = containingMethod.getContainingClass();
```
To see how the navigation works in practice, please refer to the
[code sample](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/psi_demo/src/main/java/org/intellij/sdk/psi/PsiNavigationDemoAction.java).
To see how the navigation works in practice, please refer to the [code sample](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/psi_demo/src/main/java/org/intellij/sdk/psi/PsiNavigationDemoAction.java).

View File

@ -3,11 +3,11 @@ title: Program Structure Interface (PSI)
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
The Program Structure Interface, commonly referred to as just PSI, is the layer in the _IntelliJ Platform_ that is responsible for parsing files and creating the syntactic and semantic code model that powers so many of the platform's features.
The Program Structure Interface, commonly referred to as just PSI, is the layer in the _IntelliJ Platform_ responsible for parsing files and creating the syntactic and semantic code model that powers so many of the platform's features.
* [PSI Files](/basics/architectural_overview/psi_files.md)
* [File View Providers](/basics/architectural_overview/file_view_providers.md)
* [PSI Elements](/basics/architectural_overview/psi_elements.md)
> **TIP** A very helpful tool for debugging the PSI implementation is the [PsiViewer plugin](https://plugins.jetbrains.com/plugin/227-psiviewer).
It can show you the structure of the PSI tree, the properties of every PSI element and highlight its text range.
> **TIP** A useful tool for debugging the PSI implementation is the [PsiViewer plugin](https://plugins.jetbrains.com/plugin/227-psiviewer).
> It can show you the PSI tree structure, the properties of every PSI element, and highlight its text range.

View File

@ -1,19 +1,26 @@
---
title: PSI Elements
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
<!-- Copyright 2000-2020 JetBrains s.r.o.
and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
A PSI (Program Structure Interface) file represents a hierarchy of PSI elements (so-called _PSI trees_). A single PSI file (itself being a PSI element) may contain several PSI trees in specific programming languages. A PSI element, in its turn, can have child PSI elements.
A PSI (Program Structure Interface) file represents a hierarchy of PSI elements (so-called _PSI trees_).
A single PSI file (itself being a PSI element) may contain several PSI trees in specific programming languages.
A PSI element, in its turn, can have child PSI elements.
PSI elements and operations at the level of individual PSI elements are used to explore the internal structure of source code as it is interpreted by the **IntelliJ Platform**. For example, you can use PSI elements to perform code analysis, such as [code inspections](https://www.jetbrains.com/help/idea/code-inspection.html) or [intention actions](https://www.jetbrains.com/idea/help/intention-actions.html).
PSI elements and operations at the level of individual PSI elements are used to explore the source code's internal structure as it is interpreted by the **IntelliJ Platform**.
For example, you can use PSI elements to perform code analysis, such as [code inspections](https://www.jetbrains.com/help/idea/code-inspection.html) or [intention actions](https://www.jetbrains.com/idea/help/intention-actions.html).
The [`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) class is the common base class for PSI elements.
## How do I get a PSI element?
* From an action: `e.getData(LangDataKeys.PSI_ELEMENT)`. Note: if an editor is currently open and the element under caret is a reference, this will return the result of resolving the reference. This may or may not be what you need.
* From a file by offset: `PsiFile.findElementAt()`. Note: this returns the lowest level element ("leaf") at the specified offset, which is normally a lexer token.
Most likely you should use `PsiTreeUtil.getParentOfType()` to find the element you really need.
* From an action: `e.getData(LangDataKeys.PSI_ELEMENT)`.
Note: if an editor is currently open and the element under caret is a reference, this will return the result of resolving the reference.
This may or may not be what you need.
* From a file by offset: `PsiFile.findElementAt()`.
Note: this returns the lowest level element ("leaf") at the specified offset, normally a lexer token.
Most likely, you should use `PsiTreeUtil.getParentOfType()` to find the element you really need.
* By iterating through a PSI file: using a [`PsiRecursiveElementWalkingVisitor`](upsource:///platform/core-api/src/com/intellij/psi/PsiRecursiveElementWalkingVisitor.java).
* By resolving a reference: `PsiReference.resolve()`

View File

@ -3,11 +3,14 @@ title: PSI Files
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
A PSI (Program Structure Interface) file is the root of a structure representing the contents of a file as a hierarchy of elements in a particular programming language.
A PSI (Program Structure Interface) file is the root of a structure representing a file's contents as a hierarchy of elements in a particular programming language.
The [`PsiFile`](upsource:///platform/core-api/src/com/intellij/psi/PsiFile.java) class is the common base class for all PSI files, while files in a specific language are usually represented by its subclasses. For example, the [`PsiJavaFile`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiJavaFile.java) class represents a Java file, and the [`XmlFile`](upsource:///xml/xml-psi-api/src/com/intellij/psi/xml/XmlFile.java) class represents an XML file.
Unlike `VirtualFile` and `Document`, which have application scope (even if multiple projects are open, each file is represented by the same `VirtualFile` instance), PSI has project scope (the same file is represented by multiple `PsiFile` instances if the file belongs to multiple projects open at the same time).
Unlike `VirtualFile` and `Document`, which have application scope (even if multiple projects are open, each file is represented by the same `VirtualFile` instance).
A PSI has project scope.
The same file is represented by one `PsiFile` instance for each open project to which the file belongs.
In contrast, `VirtualFile` and Document have application scope; files are represented by the same VirtualFile instance, even if multiple projects are open.
## How do I get a PSI file?
@ -27,7 +30,7 @@ To iterate over the elements in a file, use `psiFile.accept(new PsiRecursiveElem
As PSI is language-dependent, PSI files are created through the [`Language`](upsource:///platform/core-api/src/com/intellij/lang/Language.java) object, by using the `LanguageParserDefinitions.INSTANCE.forLanguage(language).createFile(fileViewProvider)` method.
Like documents, PSI files are created on demand when the PSI is accessed for a particular file.
Like documents, PSI files are created on-demand when the PSI is accessed for a particular file.
## How long do PSI files persist?
@ -45,7 +48,8 @@ To save the PSI file to disk, use the [`PsiDirectory`](upsource:///platform/core
## How do I extend PSI?
PSI can be extended to support additional languages through custom language plugins. For more details on developing custom language plugins, see the [Custom Language Support](/reference_guide/custom_language_support.md) reference guide.
PSI can be extended to support additional languages through custom language plugins.
For more details on developing custom language plugins, see the [Custom Language Support](/reference_guide/custom_language_support.md) reference guide.
## What are the rules for working with PSI?

View File

@ -3,11 +3,10 @@ title: PSI References
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
A *reference* in a PSI tree is an object that represents a link from a *usage* of a certain element in the code
to the corresponding *declaration*. *Resolving* a reference means locating the declaration to which a specific usage
refers.
A *reference* in a PSI tree is an object that represents a link from a *usage* of a particular element in the code to the corresponding *declaration*. *Resolving* a reference means locating the declaration to which a specific usage refers.
The most common type of references is defined by language semantics. For example, consider a simple Java method:
The most common type of reference is defined by language semantics.
For example, consider a simple Java method:
```java
public void hello(String message) {
@ -15,84 +14,82 @@ public void hello(String message) {
}
```
This simple code fragment contains five references. The references created by the identifiers `String`, `System`, `out` and
`println` can be resolved to the corresponding declarations in the JDK: the `String` and `System` classes, the `out` field and the
`println` method. The reference created by the second occurrence of the `message` identifier in `println(message)` can be resolved to the
`message` parameter, declared by `String message` in the method header.
This simple code fragment contains five references.
The references created by the identifiers `String`, `System`, `out`, and `println` can be resolved to the corresponding declarations in the JDK: the `String` and `System` classes, the `out` field, and the `println` method.
The reference created by the second occurrence of the `message` identifier in `println(message)` can be resolved to the `message` parameter, declared by `String message` in the method header.
Note that `String message` is not a reference, and cannot be resolved. Instead, it's a _declaration_. It does not
refer to any name defined elsewhere; instead, it defines a name by itself.
Note that `String message` is not a reference and cannot be resolved.
Instead, it's a _declaration_.
It does not refer to any name defined elsewhere; instead, it defines a name by itself.
A reference is an instance of a class implementing the [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) interface.
Note that references are distinct from PSI elements. References created by a PSI element are returned from
`PsiElement.getReferences()`, the underlying PSI element of a reference can be obtained from `PsiReference.getElement()`.
Note that references are distinct from PSI elements.
References created by a PSI element are returned from `PsiElement.getReferences()`, the underlying PSI element of a reference can be obtained from `PsiReference.getElement()`.
To *resolve* the reference - to locate the declaration being referenced - call `PsiReference.resolve()`. It's very
important to understand the difference between `PsiReference.getElement()` and `PsiReference.resolve()`. The former method returns the _source_
of a reference, while the latter returns its _target_. In the example above, for the `message` reference, `getElement()`
will return the `message` identifier on the second line of the snippet, and `resolve()` will return the `message` identifier
on the first line (inside the parameter list).
To *resolve* the reference - to locate the declaration being referenced - call `PsiReference.resolve()`.
It's very important to understand the difference between `PsiReference.getElement()` and `PsiReference.resolve()`.
The former method returns the _source_ of a reference, while the latter returns its _target_.
In the example above, for the `message` reference, `getElement()` will return the `message` identifier on the second line of the snippet, and `resolve()` will return the `message` identifier on the first line (inside the parameter list).
The process of resolving references is distinct from parsing and is not performed at the same time. Moreover, it is
not always successful. If the code currently open in the IDE does not compile, or in other situations, it's normal
for `PsiReference.resolve()` to return `null` - all code working with references must be prepared to handle that.
The process of resolving references is distinct from parsing and is not performed at the same time.
Moreover, it is not always successful.
If the code currently open in the IDE does not compile, or in other situations, it's normal for `PsiReference.resolve()` to return `null` - all code working with references must be prepared to handle that.
> **TIP** Please see also _Cache results of heavy computations_ in [Working with PSI efficiently](/reference_guide/performance/performance.md#working-with-psi-efficiently).
## Contributed References
In addition to references defined by the semantics of the programming language, the IDE recognizes many references
which are determined by the semantics of the APIs and frameworks used in code. Consider the following example:
In addition to references defined by the semantics of the programming language, the IDE recognizes many references determined by the semantics of the APIs and frameworks used in code.
Consider the following example:
```java
File f = new File("foo.txt");
```
Here, "foo.txt" has no special meaning from the point of view of the Java syntax - it's just a string literal. However,
opening this example in IntelliJ IDEA and having a file called "foo.txt" in the same directory, one
can <kbd>Ctrl/Cmd</kbd>-Click on "foo.txt" and navigate to the file. This works because the IDE recognizes the
semantics of `new File(...)` and _contributes a reference_ into the string literal passed as a parameter to the method.
Here, "foo.txt" has no special meaning from the point of view of the Java syntax - it's just a string literal.
However, opening this example in IntelliJ IDEA and having a file called "foo.txt" in the same directory, one can <kbd>Ctrl/Cmd</kbd>-Click on "foo.txt" and navigate to the file.
This works because the IDE recognizes the semantics of `new File(...)` and _contributes a reference_ into the string literal passed as a parameter to the method.
Typically, references can be contributed to elements that don't have their own references, such as string literals
and comments. References are also often contributed to non-code files, such as XML or JSON.
Typically, references can be contributed to elements that don't have their own references, such as string literals and comments.
References are also often contributed to non-code files, such as XML or JSON.
Contributing references is one of the most common ways to extend an existing language. For example, your plugin can
contribute references to Java code, even though the Java PSI is part of the platform and not defined in your plugin.
Contributing references is one of the most common ways to extend an existing language.
For example, your plugin can contribute references to Java code, even though the Java PSI is part of the platform and not defined in your plugin.
To contribute references, see the [reference contributor tutorial](/tutorials/custom_language_support/reference_contributor.md).
## References with Optional or Multiple Resolve Results
In the simplest case, a reference resolves to a single element, and if resolving fails, the
code is incorrect, and the IDE needs to highlight it as an error. However, there are cases when the situation is different.
In the simplest case, a reference resolves to a single element, and if resolving fails, the code is incorrect, and the IDE needs to highlight it as an error.
However, there are cases when the situation is different.
The first case is *soft references*. Consider the `new File("foo.txt")` example above. If the IDE can't find
the file "foo.txt", it doesn't mean that an error needs to be highlighted - maybe the file is only available at runtime.
The first case is *soft references*.
Consider the `new File("foo.txt")` example above.
If the IDE can't find the file "foo.txt", it doesn't mean that an error needs to be highlighted - maybe the file is only available at runtime.
Such references return `true` from the `PsiReference.isSoft()` method.
The second case is *polyvariant references*. Consider the case of a JavaScript program. JavaScript is a dynamically
typed language, so the IDE cannot always precisely determine which method is being called at a particular location.
The second case is *polyvariant references*.
Consider the case of a JavaScript program.
JavaScript is a dynamically typed language, so the IDE cannot always precisely determine which method is being called at a particular location.
To handle this, it provides a reference that can be resolved to multiple possible elements.
Such references implement the [`PsiPolyVariantReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiPolyVariantReference.java) interface.
For resolving a `PsiPolyVariantReference`, you call its `multiResolve()` method. The call returns an array of
[`ResolveResult`](upsource:///platform/core-api/src/com/intellij/psi/ResolveResult.java) objects. Each of the
objects identifies a PSI element and also specifies whether the result is valid. For example, if you have multiple
Java method overloads and a call with arguments not matching any of the overloads, you will get
back `ResolveResult` objects for all of the overloads, and `isValidResult()` returns `false` for all of them.
For resolving a `PsiPolyVariantReference`, you call its `multiResolve()` method.
The call returns an array of [`ResolveResult`](upsource:///platform/core-api/src/com/intellij/psi/ResolveResult.java) objects.
Each of the objects identifies a PSI element and also specifies whether the result is valid.
For example, suppose you have multiple Java method overloads and a call with arguments not matching any of the overloads. In that case, you will get back `ResolveResult` objects for all of the overloads, and `isValidResult()` returns `false` for all of them.
## Searching for References
As you already know, resolving a reference means going from usage to the corresponding declaration. To perform the
navigation in the opposite direction - from a declaration to its usages - perform a **references search**.
As you already know, resolving a reference means going from usage to the corresponding declaration.
To perform the navigation in the opposite direction - from a declaration to its usages - perform a **references search**.
To perform a search using [`ReferencesSearch`](upsource:///platform/indexing-api/src/com/intellij/psi/search/searches/ReferencesSearch.java), specify the *element* to search for, and optionally other parameters such as the
scope in which the reference needs to be searched. The created [`Query`](upsource:///platform/core-api/src/com/intellij/util/Query.java) allows obtaining all results
at once or iterating over the results one by one. The latter allows stopping processing as soon as the first (matching) result has been found.
To perform a search using [`ReferencesSearch`](upsource:///platform/indexing-api/src/com/intellij/psi/search/searches/ReferencesSearch.java), specify the *element* to search for, and optionally other parameters such as the scope in which the reference needs to be searched.
The created [`Query`](upsource:///platform/core-api/src/com/intellij/util/Query.java) allows obtaining all results at once or iterating over the results one by one.
The latter allows stopping processing as soon as the first (matching) result has been found.
## Implementing References
Please refer to the [guide](/reference_guide/custom_language_support/references_and_resolve.md) and
corresponding [tutorial](/tutorials/custom_language_support/reference_contributor.md) for more information.
Please refer to the [guide](/reference_guide/custom_language_support/references_and_resolve.md) and corresponding [tutorial](/tutorials/custom_language_support/reference_contributor.md) for more information.

View File

@ -8,7 +8,8 @@ A [`VirtualFile`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/Vir
Most commonly, a virtual file is a file in a local file system.
However, the *IntelliJ Platform* supports multiple pluggable file system implementations, so virtual files can also represent classes in a JAR file, old revisions of files loaded from a version control repository, and so on.
The VFS level deals only with binary content. Contents of a `VirtualFile` are treated as a stream of bytes, but concepts like encodings and line separators are handled on higher system levels.
The VFS level deals only with binary content.
Contents of a `VirtualFile` are treated as a stream of bytes, but concepts like encodings and line separators are handled on higher system levels.
## How do I get a virtual file?
@ -41,14 +42,15 @@ Invoking a VFS refresh might be necessary for accessing a file that has just bee
## How long does a virtual file persist?
A particular file on disk is represented by equal `VirtualFile` instances for the entire lifetime of the IDE process.
A particular file on disk is represented by equal `VirtualFile` instances for the IDE process's entire lifetime.
There may be several instances corresponding to the same file, and they can be garbage-collected.
The file is a `UserDataHolder`, and the user data is shared between those equal instances.
If a file is deleted, its corresponding VirtualFile instance becomes invalid (`isValid()` returns `false`), and operations cause exceptions.
## How do I create a virtual file?
Usually, you don't. As a general rule, files are created either through the PSI API or through the regular `java.io.File` API.
Usually, you don't.
As a general rule, files are created either through the PSI API or through the regular `java.io.File` API.
If one needs to create a file through VFS, use `VirtualFile.createChildData()` to create a `VirtualFile` instance and `VirtualFile.setBinaryContent()` to write some data to the file.
@ -56,7 +58,8 @@ If one needs to create a file through VFS, use `VirtualFile.createChildData()` t
> **NOTE** See [Virtual file system events](/basics/virtual_file_system.md#virtual-file-system-events) for important details.
Implement [`BulkFileListener`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/newvfs/BulkFileListener.java) and subscribe to the [message bus](/reference_guide/messaging_infrastructure.md) topic `VirtualFileManager.VFS_CHANGES`. For example:
Implement [`BulkFileListener`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/newvfs/BulkFileListener.java) and subscribe to the [message bus](/reference_guide/messaging_infrastructure.md) topic `VirtualFileManager.VFS_CHANGES`.
For example:
```java
project.getMessageBus().connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {

View File

@ -19,14 +19,13 @@ The `Disposer` supports chaining `Disposables` in parent-child relationships.
## Automatically Disposed Objects
A number of objects are disposed automatically by the platform if they implement the `Disposable` interface.
The most important type of such objects is [services](/basics/plugin_structure/plugin_services.md). Application-level
services are automatically disposed by the platform when the IDE is closed, or the plugin providing the service is
unloaded. Project-level services are disposed when the project is closed or the plugin is unloaded.
Many objects are disposed automatically by the platform if they implement the `Disposable` interface.
The most important type of such objects is [services](/basics/plugin_structure/plugin_services.md).
Application-level services are automatically disposed by the platform when the IDE is closed or the plugin providing the service is unloaded.
Project-level services are disposed when the project is closed, or the plugin is unloaded.
Note that extensions registered in `plugin.xml` are *not* automatically disposed. If an extension requires executing
some code to dispose it, you need to define a service and to put the code in its `dispose()` method or use it as a parent
disposable.
Note that extensions registered in `plugin.xml` are *not* automatically disposed.
If an extension requires executing some code to dispose it, you need to define a service and to put the code in its `dispose()` method or use it as a parent disposable.
## The Disposer Singleton
@ -50,28 +49,26 @@ One of the parent `Disposables` provided by the IntelliJ Platform can be chosen,
Use the following guidelines to choose the correct parent:
* For resources required for the entire lifetime of a plugin, use an application or project level [service](/basics/plugin_structure/plugin_services.md).
* For resources required for a plugin's entire lifetime, use an application or project level [service](/basics/plugin_structure/plugin_services.md).
* For resources required while a [dialog](/user_interface_components/dialog_wrapper.md) is displayed, use `DialogWrapper.getDisposable()`.
* For resources required while a [tool window](/user_interface_components/tool_windows.md) tab is displayed, pass your instance implementing `Disposable` to `Content.setDisposer()`.
* For resources with a shorter lifetime, create a disposable using `Disposer.newDisposable()` and dispose it manually
using `Disposable.dispose()`. Note that it's always best to specify a parent for such a disposable (e.g., a project-level service),
so that there is no memory leak if the `Disposable.dispose()` call is not reached because of an exception or a programming error.
* For resources with a shorter lifetime, create a disposable using `Disposer.newDisposable()` and dispose it manually using `Disposable.dispose()`.
Note that it's always best to specify a parent for such a disposable (e.g., a project-level service), so that there is no memory leak if the `Disposable.dispose()` call is not reached because of an exception or a programming error.
> **WARNING** Even though `Application` and `Project` implement `Disposable`, they must NEVER be used as parent disposables in plugin code.
Disposables registered using those objects as parents will not be disposed when the plugin is unloaded, leading to memory leaks.
The flexibility of the `Disposer` API means that if the parent instance is chosen unwisely, the child may consume resources for longer than required.
Continuing to use resources when they are no longer needed can be a severe source of contention due to leaving some zombie objects behind as a result of each invocation.
The `Disposer` API's flexibility means that if the parent instance is chosen unwisely, the child may consume resources for longer than required.
Continuing to use resources when they are no longer needed can be a severe source of contention due to leaving some zombie objects behind due to each invocation.
An additional challenge is that these kinds of issues won't be reported by the regular leak checker utilities, because technically, it's not a memory leak from the test suite perspective.
For example, if a UI component created for a specific operation uses a project-level service as a parent disposable,
the entire component will remain in memory after the operation is complete. This creates memory pressure and can waste
CPU cycles on processing events that are no longer relevant for anything.
For example, suppose a UI component created for a specific operation uses a project-level service as a parent disposable. In that case, the entire component will remain in memory after the operation is complete.
This creates memory pressure and can waste CPU cycles on processing events that are no longer relevant.
### Registering Listeners with Parent Disposable
Many IntelliJ Platform APIs for registering listeners either require passing a parent disposable or have overloads that
take a parent disposable. For example:
Many IntelliJ Platform APIs for registering listeners either require passing a parent disposable or have overloads that take a parent disposable.
For example:
```java
public abstract class EditorFactory {
@ -82,21 +79,21 @@ public abstract class EditorFactory {
}
```
Methods with a `parentDisposable` parameter automatically unsubscribe the listener when the corresponding parent disposable
is disposed. Using such methods is always preferable to removing listeners explicitly from the `dispose` method, because
it requires less code and is easier to verify for correctness.
Methods with a `parentDisposable` parameter automatically unsubscribe the listener when the corresponding parent disposable is disposed.
Using such methods is always preferable to removing listeners explicitly from the `dispose` method because it requires less code and is easier to verify for correctness.
To choose the correct parent disposable, use the guidelines from the previous section.
The same rules apply to [message bus](/reference_guide/messaging_infrastructure.md) connections. Always pass a parent disposable to `MessageBus.connect()`, and make sure
it has the shortest possible lifetime.
The same rules apply to [message bus](/reference_guide/messaging_infrastructure.md) connections.
Always pass a parent disposable to `MessageBus.connect()`, and make sure it has the shortest possible lifetime.
### Determining Disposal Status
You can use `Disposer.isDisposed()` to check whether a `Disposable` has already been disposed.
This check is useful, for example, for an asynchronous callback to a `Disposable` that may be disposed before the callback is executed.
In such a case, the best strategy is usually to do nothing and return early.
> **WARNING** Non-disposed objects shouldn't hold onto references to disposed objects, as this constitutes a memory leak. Once a `Disposable` is released, it should be completely inactive, and there's no reason to refer to it anymore.
> **WARNING** Non-disposed objects shouldn't hold onto references to disposed objects, as this constitutes a memory leak.
> Once a `Disposable` is released, it should be completely inactive, and there's no reason to refer to it anymore.
### Ending a Disposable Lifecycle
A plugin can manually end a `Disposable` lifecycle by calling `Disposer.dispose(Disposable)`.
@ -106,8 +103,7 @@ This method handles recursively disposing of all the `Disposable` child descenda
Creating a class requires implementing the `Disposable` interface and defining the `dispose()` method.
In many cases, when the object implements `Disposable` only to be used as a parent disposable, the implementation of the
method will be completely empty.
In many cases, when the object implements `Disposable` only to be used as a parent disposable, the method's implementation will be completely empty.
An example of a non-trivial `dispose` implementation is shown below:
@ -135,7 +131,8 @@ Regardless, it illustrates the basic pattern, which is:
* The `Foo` disposable is registered as a child of `parentDisposable` in the constructor.
* The `dispose()` method consolidates the necessary release actions and will be called by the `Disposer`.
> **WARNING** Never call `Disposable.dispose()` directly because it bypasses the parent-child relationships established in `Disposer`. Always call `Disposer.dispose(Disposable)` instead.
> **WARNING** Never call `Disposable.dispose()` directly because it bypasses the parent-child relationships established in `Disposer`.
> Always call `Disposer.dispose(Disposable)` instead.
## Diagnosing Disposer Leaks
@ -171,11 +168,12 @@ The following snippet represents the sort of "memory leak detected" error encoun
```
> **TIP** The first part of the callstack is unrelated to diagnosing the memory leak. Instead, pay attention to the second part of the call stack, after `Caused by: java.lang.Throwable`.
> **TIP** The first part of the callstack is unrelated to diagnosing the memory leak.
> Instead, pay attention to the second part of the call stack, after `Caused by: java.lang.Throwable`.
In this specific case, the IntelliJ Platform ([`CoreProgressManager`](upsource:///platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java)) started a task that contained the `DynamicWizard` code.
That code, in turn, allocated a `Project` that was never disposed by the time the application exited.
That is a promising initial place to start digging.
In turn, that code allocated a `Project` that was never disposed by the time the application exited.
That is a promising place to start digging.
The above memory leak was ultimately caused by failing to pass a `Project` instance to a function responsible for registering it for disposal.
Often the fix for a memory leak is as simple as understanding the memory scope of the object being allocated - often a UI container, project, or application - and making sure a `Disposer.register()` call is made appropriately for it.
Often the fix for a memory leak is as simple as understanding the memory scope of the object being allocated - usually a UI container, project, or application - and making sure a `Disposer.register()` call is made appropriately for it.

View File

@ -5,8 +5,7 @@ redirect_from:
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
This FAQ is a topical index of questions that have been asked (and answered) on our
[IntelliJ IDEA Open API and Plugin Development forum](https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development).
This FAQ is a topical index of questions that have been asked (and answered) on our [IntelliJ IDEA Open API and Plugin Development forum](https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development).
## Open-Source Plugins
* [How do I compile the Scala plugin?](https://github.com/jetbrains/intellij-scala#setting-up-the-project)
@ -19,7 +18,7 @@ This FAQ is a topical index of questions that have been asked (and answered) on
* [How do I add a main menu item?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206750335-Add-new-Main-menu-option-for-plugin)
* [How do I customize the "New..." menu?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206765055-Overriding-the-New-context-menu-in-the-Project-view)
* [How do I customize the compiler output context menu?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206142169-How-to-add-a-menu-item-below-Exclude-From-Compile-)
* [How do I get the context of an action (selected file, active project etc.)?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206756455-Question-about-Actions)
* [How do I get the context of an action (selected file, active project, etc.)?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206756455-Question-about-Actions)
* [How do I change the icon of an action dynamically?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206763405-How-to-dynamically-change-icons-in-the-tool-bar-)
* [How do I add icons to the IDEA toolbar?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206151289-How-to-add-icons-to-the-toolbar-)
* [Where do I get the list of built-in action IDs?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206126699-List-of-built-in-action-ID-s-)

View File

@ -3,7 +3,10 @@ title: Creating Your First Plugin
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
This documentation section will help you get started with developing plugins for the *IntelliJ Platform*. You can use either [IntelliJ IDEA Community Edition](https://www.jetbrains.com/idea/download/) or [IntelliJ IDEA Ultimate](https://www.jetbrains.com/idea/download/) as your IDE (it is highly recommended to use the latest available version). Both include the complete set of plugin development tools. To become more familiar with *IntelliJ IDEA*, please refer to the [IntelliJ IDEA Web Help](https://www.jetbrains.com/idea/help/).
This documentation section will help you get started with developing plugins for the *IntelliJ Platform*.
You can use either [IntelliJ IDEA Community Edition](https://www.jetbrains.com/idea/download/) or [IntelliJ IDEA Ultimate](https://www.jetbrains.com/idea/download/) as your IDE (it is highly recommended to use the latest available version).
Both include the complete set of plugin development tools.
To become more familiar with *IntelliJ IDEA*, please refer to the [IntelliJ IDEA Web Help](https://www.jetbrains.com/idea/help/).
There are three supported workflows available for building plugins.
The recommended workflow for new projects is to [use GitHub Template](#using-github-template) or to [use Gradle](#using-gradle) to create everything from scratch.

View File

@ -1,6 +1,7 @@
---
title: Build Number Ranges
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
<style>
table {
width:100%;
@ -24,11 +25,17 @@ The number consists of the following parts:
* Branch number (`162`)
* Build number in the branch (`94`)
Since version 2016.2 of the *IntelliJ Platform*, branch numbers are based on the `YYYY.R` [IDE release version numbers](https://blog.jetbrains.com/blog/2016/03/09/jetbrains-toolbox-release-and-versioning-changes/). The branch number takes the last two digits of the year, and the `R` release number. For example, `162` for 2016.2, `163` for 2016.3, `171` for 2017.1. In this scheme `IU-162.94` corresponds to the 2016.2 release.
Since version 2016.2 of the *IntelliJ Platform*, branch numbers are based on the `YYYY.R` [IDE release version numbers](https://blog.jetbrains.com/blog/2016/03/09/jetbrains-toolbox-release-and-versioning-changes/).
The branch number takes the last two digits of the year and the `R` release number.
For example, `162` for 2016.2, `163` for 2016.3, `171` for 2017.1.
In this scheme, `IU-162.94` corresponds to the 2016.2 release.
Starting with 2016.2 the build number may also have multiple components: `IU-162.94`, `IU-162.94.11`, `IU-162.94.11.256.42`. This gives more flexibility for third-party plugins and IDE developers. Plugins may specify compatibility versions more precisely; IDE vendors may have build numbers that are based on a specific *IntelliJ Platform* version and also specify additional internal version (e.g. `256.42` in `XX-162.94.11.256.42`) to allow plugin developers for their IDE to specify compatibility.
Starting with 2016.2, the build number may also have multiple components: `IU-162.94`, `IU-162.94.11`, `IU-162.94.11.256.42`.
This gives more flexibility for third-party plugins and IDE developers.
Plugins may specify compatibility versions more precisely; IDE vendors may have build numbers based on a specific *IntelliJ Platform* version and specify additional internal version (e.g. `256.42` in `XX-162.94.11.256.42`) to allow plugin developers for their IDE to specify compatibility.
Multi-part build numbers can also be used in the `since-build` and `until-build` attributes of `idea-version`. Usually you should omit the product ID and use only the branch number and build number, for example:
Multi-part build numbers can also be used in the `since-build` and `until-build` attributes of `idea-version`.
Usually you should omit the product ID and use only the branch number and build number, for example:
```xml
<idea-version since-build="94.539"/>
@ -59,7 +66,8 @@ Multi-part build numbers can also be used in the `since-build` and `until-build`
| [163](https://github.com/JetBrains/intellij-community/tree/163) | 2016.3 |
| [162](https://github.com/JetBrains/intellij-community/tree/162) | 2016.2 |
Note that there is no `170`. In the `YYYY.R` versioning scheme, the `R` part starts at 1.
Note that there is no `170`.
In the `YYYY.R` versioning scheme, the `R` part starts at 1.
### IntelliJ Platform Based Products of Pre-2016.2 IDE Versions

View File

@ -7,16 +7,16 @@ redirect_from:
> **NOTE** For new projects, it is highly recommended to use [Gradle](/tutorials/build_system.md).
This section explains how you can create a new plugin project from scratch using the New Project wizard. Optionally, you can import an existing project or import a project from external models. You can also add a new plugin module to a current *IntelliJ Platform* project.
This section explains how you can create a new plugin project from scratch using the New Project wizard.
Optionally, you can import an existing project or import a project from external models.
You can also add a new plugin module to a current *IntelliJ Platform* project.
For more information, refer to the [IntelliJ IDEA Web Help](https://www.jetbrains.com/idea/help/new-project-wizard.html).
### To Create an IntelliJ Platform Plugin Project:
* On the main menu, choose **File \| New \| Project**. The *New Project*
wizard starts.
* On the main menu, choose **File \| New \| Project**.
The *New Project* wizard starts.
![New Project Wizard](img/new_project_wizard.png)
* Set *IntelliJ Platform Plugin* project type.
* Click **Next**.
* Set the desired project name.
@ -25,14 +25,11 @@ For more information, refer to the [IntelliJ IDEA Web Help](https://www.jetbrain
### To Create an IntelliJ Platform Plugin Module
* Select **File \| New \| Module** and choose the *IntelliJ Platform Plugin* module type
![IntelliJ Platform Plugin Module](img/intellij_platform_plugin_module.png)
<br/>
<br/>
<br/>
<br/>
* Enter your desired plugin name.
* Go to **File \| Project Structure** and select the newly created *IntelliJ Platform SDK* as the default SDK for the plugin module:
![Set Plugin Module SDK](img/set_plugin_module_sdk.png)
### Adding Code to the Project

View File

@ -8,18 +8,20 @@ Before your custom plugin can be used, it must be deployed: built, installed, an
To deploy a plugin:
* Make your project by invoking **Build \| Build Project** or **Build \| Build Module \<module name\>**.
* Prepare your plugin for deployment. In the main menu, select **Build \| Prepare Plugin Module \<module name\> for Deployment**.
* Prepare your plugin for deployment.
In the main menu, select **Build \| Prepare Plugin Module \<module name\> for Deployment**.
![Prepare Plugin for Deployment](deploying_plugin/img/prepare_plugin_for_deployment.png)
* If the plugin module does not depend on any libraries, a `.jar` archive will be created. Otherwise, a `.zip` archive will be created, including all the plugin libraries specified in the project settings.
* If the plugin module does not depend on any libraries, a `.jar` archive will be created.
Otherwise, a `.zip` archive will be created, including all the plugin libraries specified in the project settings.
![Jar Saved Notification](deploying_plugin/img/jar_saved_notification.png)
* [Install](https://www.jetbrains.com/help/idea/managing-plugins.html#installing-plugins-from-disk)
the newly created archive/jar file from disk. The `editor_basics` code sample builds the plugin archive/jar into the `editor_basics` project folder:
the newly created archive/jar file from disk.
The `editor_basics` code sample builds the plugin archive/jar into the `editor_basics` project folder:
![Jar File Location](deploying_plugin/img/jar_location.png)
* Restart your IDE so the changes will take effect.

View File

@ -30,11 +30,11 @@ A working definition of a dependency is that a plugin project cannot be run with
Declaring a dependency on a module also expresses a plugin's compatibility with a product in that the IntelliJ Platform determines whether a product contains the correct modules to support a plugin before loading it.
[Part I](/basics/plugin_structure/plugin_dependencies.md) of this document describes the syntax for declaring plugin dependencies and optional plugin dependencies.
Part II of this document (below) describes the functionality of the IntelliJ Platform modules to aid in determining the dependencies of a plugin.
Part II of this document (below) describes the IntelliJ Platform modules' functionality to aid in determining the dependencies of a plugin.
The way dependency declarations are handled by the Intellij Platform is determined by the contents of the `plugin.xml` file:
* If a plugin does not declare any dependencies in its `plugin.xml` file, or if it declares dependencies only on other plugins but not modules, it's assumed to be a legacy plugin and is loaded only in IntelliJ IDEA.
This configuration of dependency declaration is deprecated; do not use it for new plugin projects.
This configuration of the dependency declaration is deprecated; do not use it for new plugin projects.
* If a plugin declares at least _one_ module dependency in its `plugin.xml` file, the plugin is loaded if an IntelliJ Platform-based product contains _all the modules and plugins_ on which the plugin has declared a dependency.
## Modules
@ -50,7 +50,7 @@ A core set of modules are available in all products based on the IntelliJ Platfo
These modules provide a set of shared functionality.
The following table lists modules that are currently available in all products.
> **NOTE** All plugins should declare a dependency on **`com.intellij.modules.platform`** as an indication of dependence on shared functionality.
> **NOTE** All plugins should declare a dependency on **`com.intellij.modules.platform`** to indicate dependence on shared functionality.
| Module for `<depends>` Element<br>Declaration in `plugin.xml` File | <br>Functionality |
|--------------------------------------|----------------------------------------------------------------------------------------------------------------|
@ -65,13 +65,13 @@ As of this writing, if a plugin: **A)** is dependent _only_ on one or more of th
### Modules Specific to Functionality
More specialized functionality is also delivered via modules and plugins in IntelliJ Platform-based products.
For example, the `com.intellij.modules.python` module supports the Python language-specific functionality.
If a plugin uses functionality from this module, such as Python-specific inspections and refactoring, it must declare a dependency on this module.
If a plugin uses this module's functionality, such as Python-specific inspections and refactoring, it must declare a dependency on this module.
Note that not all products define and declare modules.
For example, PhpStorm does not have its own module, but the product itself depends on (and ships with) the PHP language plugin.
A plugin project is compatible with PHP functionality if it declares a dependency on this PHP language plugin.
The following table lists(1) modules or built-in plugins that provide specific functionality, and the products that currently ship with them.
The following table lists(1) modules or built-in plugins that provide specific functionality, and the products currently shipping with them.
| Module or Plugin for `<depends>` Element<br>Declaration in `plugin.xml` File | <br>Functionality | IntelliJ Platform-Based<br>Product Compatibility |
|------------------------------------------------------------------------------|--------------------|------------------------------------------|
@ -91,7 +91,7 @@ The following table lists(1) modules or built-in plugins that provide specific f
| `JavaScript` | **JavaScript** language PSI Model, Inspections, Intentions, Completion, Refactoring, Test Framework | WebStorm, and other products if the JavaScript plugin is installed. |
**Notes about Module and Plugin Dependency:**
**(1)** This table is not exhaustive, there are other modules currently available in JetBrains' IntelliJ Platform-based IDEs.
**(1)** This table is not exhaustive; other modules are currently available in JetBrains' IntelliJ Platform-based IDEs.
To see a list of modules, invoke the [code completion](https://www.jetbrains.com/help/idea/auto-completing-code.html#4eac28ba) feature for the `<depends>` element contents while editing the `plugin.xml` file.
**(2)** The [Java language functionality](https://blog.jetbrains.com/platform/2019/06/java-functionality-extracted-as-a-plugin/) was extracted as a plugin in version 2019.2 of the IntelliJ Platform.
@ -115,7 +115,7 @@ If the project is not up to date, [Reimport the Gradle project](https://www.jetb
Reimporting the project will automatically update the dependencies.
In the Project Window, select Project View and scroll to the bottom to see [External Libraries](https://www.jetbrains.com/help/idea/project-tool-window.html#content_pane).
Look for the library `Gradle:unzipped.com.jetbrains.plugins:foo:`, where "foo" matches, or is similar to, the contents of the `<depends>` tags in `plugin.xml` or the `intellij.plugins` declaration in `build.gradle`.
Look for the library `Gradle:unzipped.com.jetbrains.plugins:foo:`, where "foo" matches, or is similar to the contents of the `<depends>` tags in `plugin.xml` or the `intellij.plugins` declaration in `build.gradle`.
The image below shows the External Libraries for the example plugin project configuration explained in [Configuring build.gradle](/products/dev_alternate_products.md#configuring-buildgradle-using-the-intellij-idea-product-attribute) and [Configuring plugin.xml](/products/dev_alternate_products.md#configuring-pluginxml).
![Example PhpStorm Project Libraries](img/php_prj_libs.png){:width="700px"}
@ -124,7 +124,7 @@ Expand the External Library (as shown) to reveal the JAR files contained in the
Drill down into the JAR files to expose the packages and (decompiled) classes.
### Exploring APIs as an Extender
If a project is dependent on a plugin or module, in some cases the project can also [extend](/basics/plugin_structure/plugin_extensions.md) the functionality available from the plugin or module.
If a project is dependent on a plugin or module, in some cases, the project can also [extend](/basics/plugin_structure/plugin_extensions.md) the functionality available from the plugin or module.
To browse the opportunities for extension, start by placing the cursor on the contents of the `<depends>` elements in the project's `plugin.xml` file.
Use the [Go to Declaration](https://www.jetbrains.com/help/idea/navigating-through-the-source-code.html#go_to_declaration) IDE feature to navigate to the `plugin.xml` file for the plugin on which the project depends.
@ -151,4 +151,3 @@ The compatibility information determines if plugins are available at the plugin
## Platform API Version Compatibility
The API of _IntelliJ Platform_ and bundled plugins may change between releases.
The significant changes that may break plugins are listed on [Incompatible Changes in IntelliJ Platform and Plugins API](/reference_guide/api_changes_list.md) page.

View File

@ -4,14 +4,12 @@ title: Publishing a Plugin
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
When your plugin is ready, you can publish it to a plugin repository so that other users can install it.
You can choose to publish it on the [JetBrains Plugins Repository](https://plugins.jetbrains.com)
or a [custom plugin repository](/basics/getting_started/update_plugins_format.md).
You can choose to publish it on the [JetBrains Plugins Repository](https://plugins.jetbrains.com) or a [custom plugin repository](/basics/getting_started/update_plugins_format.md).
> **TIP** Please see [Marketing](/appendix/resources/marketing.md) for remarks on how to prepare your plugin for optimal presentation.
### Publishing to the JetBrains Plugins Repository
To upload your plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com),
you must log in with your personal JetBrains Account.
To upload your plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com), you must log in with your personal JetBrains Account.
**To get your JetBrains account:**
@ -20,10 +18,9 @@ you must log in with your personal JetBrains Account.
**To upload your plugin to JetBrains Plugins Repository:**
1. [Login to JetBrains Plugins Repository](https://plugins.jetbrains.com/author/me) with your personal JetBrains account.
1. [Log in to JetBrains Plugins Repository](https://plugins.jetbrains.com/author/me) with your personal JetBrains account.
2. On your Profile page that opens, click **Add new plugin**.
3. Fill in the **Add new plugin** form that opens and click the **Add the plugin** button to upload your plugin.
### Publishing a Plugin to a Custom Plugin Repository
If you plan to publish your plugin to a repository _other than_ the [JetBrains Plugins Repository](https://plugins.jetbrains.com),
please refer to the [Publishing to Custom Plugin Repositories](update_plugins_format.md) documentation.
If you plan to publish your plugin to a repository _other than_ the [JetBrains Plugins Repository](https://plugins.jetbrains.com), please refer to the [Publishing to Custom Plugin Repositories](update_plugins_format.md) documentation.

View File

@ -3,7 +3,8 @@ title: Running and Debugging a Plugin
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
It's possible to run and debug a plugin directly from the *IntelliJ IDEA*. You need a configured special profile (a *Plugin* Run/Debug configuration) that specifies the plugin module, VM parameters, and other specific options. When you run such a profile, it launches the IDE with your plugin installed.
It's possible to run and debug a plugin directly from the *IntelliJ IDEA*.
You need a configured special profile (a *Plugin* Run/Debug configuration) that specifies the plugin module, VM parameters, and other specific options. When you run such a profile, it launches the IDE with your plugin installed.
See [IDE Development Instances](/basics/ide_development_instance.md) for more information about configuration and advanced settings.

View File

@ -9,46 +9,46 @@ title: Setting Up a Development Environment
Use the following checklist to ensure that you are ready to develop your custom plugins.
- **Get IntelliJ IDEA CE source code** on your local computer. Getting IntelliJ IDEA CE source code is not a requirement for plugin development, but having it makes debugging your plugins much more straightforward. For detailed instructions, refer to the _Getting IntelliJ IDEA Community Edition Source Code_ section of [Check Out And Build Community Edition](upsource:///README.md). Note that building IntelliJ IDEA CE from source code is not required for plugin development.
- **Get IntelliJ IDEA CE source code** on your local computer.
Getting IntelliJ IDEA CE source code is not a requirement for plugin development, but having it makes debugging your plugins much more straightforward.
For detailed instructions, refer to the _Getting IntelliJ IDEA Community Edition Source Code_ section of [Check Out And Build Community Edition](upsource:///README.md).
Note that building IntelliJ IDEA CE from source code is not required for plugin development.
- **Plugin DevKit** plugin must be [enabled in IntelliJ IDEA](https://www.jetbrains.com/help/idea/managing-plugins.html).
- **IntelliJ Platform SDK** must be configured for your IDEA project. For more information, see below.
- **IntelliJ Platform SDK** must be configured for your IDEA project.
For more information, see below.
### Configuring IntelliJ Platform SDK
To set up your plugin development environment:
* Create a new *IntelliJ Platform SDK* under **File \| Project Structure**:
![Create IntelliJ Platform SDK](img/create_intellij_idea_sdk.png)
<br/>
<br/>
<br/>
<br/>
* Specify the installation folder of the *IntelliJ IDEA Community Edition* as the home directory.
> **WARNING** You may use IntelliJ IDEA Ultimate as an alternative, but debugging the core code will only work with the *Community Edition*.
> **WARNING** You may use IntelliJ IDEA Ultimate as an alternative, but debugging the core code will only work with the *Community Edition*.
![Set Home Directory](img/set_home_directory.png)
<br/>
<br/>
* Select **1.8** as the default Java SDK. See the _IntelliJ Build Configuration_ section of [Check Out And Build Community Edition](upsource:///README.md) for instructions about creating **1.8** Java SDK.
<br/>
<br/>
* Select **1.8** as the default Java SDK.
See the _IntelliJ Build Configuration_ section of [Check Out And Build Community Edition](upsource:///README.md) for instructions about creating **1.8** Java SDK.
![Set IDEA JDK](img/set_java_sdk.png)
<br/>
<br/>
<br/>
<br/>
* In the Sourcepath tab of the SDK settings, click the *Add* button:
![Add Sourcepath](img/add_sourcepath.png)
<br/>
<br/>
<br/>
<br/>
* Specify the source code directory for the *IntelliJ IDEA Community Edition*:
![Specify Source Paths](img/community_sources_directory.png)
<br/>
<br/>
<br/>
<br/>
* Specify the **Sandbox Home** directory.
The *Sandbox Home* directory stores the settings of the IDE development instance launched from a Plugin Project's **Run** configuration.
Shown below is the default *Sandbox Home* directory for a user on Mac OS X. Any directory can be chosen as the *Sandbox Home* location.
Shown below is the default *Sandbox Home* directory for a user on Mac OS X.
Any directory can be chosen as the *Sandbox Home* location.
Use the ellipsis button (shown below) to define a custom location.
See the [IDE Development Instances](/basics/ide_development_instance.md) page for more information about default *Sandbox Home* directory
locations and contents.
See the [IDE Development Instances](/basics/ide_development_instance.md) page for more information about default *Sandbox Home* directory locations and contents.
![Specify Sandbox Path](img/plugins-sandbox.png)

View File

@ -3,25 +3,23 @@ title: Publishing a Plugin to a Custom Plugin Repository
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
If you intend to use a plugin repository _other than_ the [JetBrains Plugins Repository](https://plugins.jetbrains.com),
you will need to:
If you intend to use a plugin repository _other than_ the [JetBrains Plugins Repository](https://plugins.jetbrains.com), you will need to:
* Create and maintain an `updatePlugins.xml` file on the HTTPS web server you are using for your custom repository.
This file describes all the plugins available in your custom repository and each plugin's download URL.
* Upload your plugin JAR/ZIP file to an HTTPS web server. This can be the same web server you are using for the custom repository
or a different HTTPS web server.
* Upload your plugin JAR/ZIP file to an HTTPS web server.
This can be the same web server you are using for the custom repository or a different HTTPS web server.
* Add the URL for the custom repository to the JetBrains IDE [Repository Settings/Preferences](https://www.jetbrains.com/help/idea/managing-plugins.html#repos).
## Describing Your Plugins in updatePlugins.xml File
Every custom plugin repository must have at least one `updatePlugins.xml` file to describe the latest available version
for every hosted plugin. The description in `updatePlugins.xml` is used by JetBrains IDEs to locate plugins by attributes
such as id, IDE version, and plugin version. These attributes are displayed by JetBrains IDEs to help users select or upgrade plugins.
Every custom plugin repository must have at least one `updatePlugins.xml` file to describe every hosted plugin's latest available version.
The description in `updatePlugins.xml` is used by JetBrains IDEs to locate plugins by attributes such as id, IDE version, and plugin version.
These attributes are displayed by JetBrains IDEs to help users select or upgrade plugins.
The description also tells the JetBrains IDE where to download the plugin itself.
A custom plugin repository's `updatePlugins.xml` file is constructed and maintained by the administrator of
the repository. More than one `updatePlugins.xml` file may be required if consumers of the custom repository are using more
than one version of a JetBrains IDE. For example `updatePlugins-182.xml`, `updatePlugins-183.xml` for IntelliJ IDEA 2018.2 and 2018.3 respectively.
Each `updatePlugins-*.xml` file will have a unique URL that is added to the JetBrains IDE
[Repository Settings/Preferences](https://www.jetbrains.com/help/idea/managing-plugins.html#repos).
A custom plugin repository's `updatePlugins.xml` file is constructed and maintained by the repository administrator.
More than one `updatePlugins.xml` file may be required if the custom repository consumers are using more than one version of a JetBrains IDE.
For example, `updatePlugins-182.xml`, `updatePlugins-183.xml` for IntelliJ IDEA 2018.2 and 2018.3, respectively.
Each `updatePlugins-*.xml` file will have a unique URL that is added to the JetBrains IDE [Repository Settings/Preferences](https://www.jetbrains.com/help/idea/managing-plugins.html#repos).
### Format of updatePlugins.xml File
The format of an `updatePlugins.xml` file is simply a list of sequential elements that describe each plugin:
@ -59,17 +57,15 @@ The format of an `updatePlugins.xml` file is simply a list of sequential element
* Multiple plugins with the same `id` but different `idea-version` attributes must be split into separate `updatePlugins-*.xml` files.
### Optional updatePlugin.xml Elements
Can additional elements be added to `updatePlugins.xml`? Yes, but it's advisable only if needed. The additional elements will have
to be synchronized with each plugin's `plugin.xml` file.
Can additional elements be added to `updatePlugins.xml`? Yes, but it's advisable only if needed.
The additional elements will have to be synchronized with each plugin's `plugin.xml` file.
During plugin installation the JetBrains IDE reads the plugin JAR/ZIP file, and thereafter displays more information about the plugin.
What additional information might help a user select a plugin when
[browsing the custom plugin repository](https://www.jetbrains.com/help/idea/managing-plugins.html#repos)
before installation? The answer depends on the plugins and repository consumers. Here are the candidate elements:
What additional information might help a user select a plugin when [browsing the custom plugin repository](https://www.jetbrains.com/help/idea/managing-plugins.html#repos) before installation? The answer depends on the plugins and repository consumers.
Here are the candidate elements:
| Element | Effects & Requirements |
|:-------------------------------------------------------------|:----------------------------|
| `<name>`<br>My Plugin Name<br>`</name>` | By default the name of the plugin JAR/ZIP file is displayed before installation. <br>Using the `<name>` element displays the name of the plugin. <br>Contents should match the `<name>` element contents in the plugins's `plugin.xml` file to avoid confusion. |
| `<description>`<br>My plugin is awesome<br>`</description>` | By default no description for the plugin is displayed before installation. <br>Using the `<description>` element will cause a description to be displayed before installation. <br>Contents should match the `<description>` element contents in the plugins's `plugin.xml` file to avoid confusion. <br>Optionally, an enclosing `<![CDATA[ ]]>` element can be used if the description needs to contain HTML tags. |
| `<change-notes>`<br>Added cool feature<br>`</change-notes>` | By default no change notes for the plugin are displayed before installation. <br>Using the `<change-notes>` element will cause a description of changes to be displayed before installation. <br>Contents should match the `<change-notes>` element contents in the plugin's `plugin.xml` file to avoid confusion. <br>Optionally, an enclosing `<![CDATA[ ]]>` element can be used if the change notes need to contain HTML tags. |

View File

@ -5,7 +5,8 @@ title: Using DevKit
> **NOTE** For new projects, it is highly recommended to use [Gradle](/tutorials/build_system.md).
_Plugin DevKit_ is a bundled IntelliJ IDEA plugin for developing plugins for the IntelliJ Platform using IntelliJ IDEA's build system. It provides its custom SDK type and a set of actions for building plugins within the IDE.
_Plugin DevKit_ is a bundled IntelliJ IDEA plugin for developing plugins for the IntelliJ Platform using IntelliJ IDEA's build system.
It provides its custom SDK type and a set of actions for building plugins within the IDE.
In this section:

View File

@ -12,7 +12,7 @@ This page describes how to control some of the settings for the Development Inst
> **TIP** Please see also [Advanced Configuration](https://www.jetbrains.com/help/idea/tuning-the-ide.html) for general VM options and properties.
## Using a JetBrains Runtime for the Development Instance
A common use case is to develop (build) a plugin project against a JDK, e.g., Java 8, and then run or debug the plugin in a Development Instance of the IDE.
An everyday use case is to develop (build) a plugin project against a JDK, e.g., Java 8, and then run or debug the plugin in a Development Instance of the IDE.
In such a situation, Development Instance must use a JetBrains Runtime (JBR) rather than the JDK used to build the plugin project.
The JetBrains Runtime is an environment for running IntelliJ Platform-based IDEs on Windows, macOS, and Linux.
@ -21,10 +21,9 @@ A version of the JetBrains Runtime is bundled with all IntelliJ Platform-based I
To produce accurate results while running or debugging a plugin project in a Development Instance, follow the procedures below to ensure the Development Instance uses a JetBrains Runtime.
### Determining a JetBrains Runtime Version
The JetBrains Runtime is determined from the JDK version used to build the plugin project.
If a plugin is being developed against the Java 8 SE Development Kit 8 for macOS, for example, `jdk-8u212-macosx-x64.dmg`.
(This example will use macOS, but Windows and Linux follow the same procedure.)
To acquire the compatible JetBrains Runtime:
The JetBrains Runtime is determined from the JDK version used to build the plugin project, regardless of whether it is built on macOS, Windows, or Linux.
For example, if a plugin is developed against the Java 8 SE Development Kit 8 for macOS (`jdk-8u212-macosx-x64.dmg`) to acquire the compatible JetBrains Runtime:
* Go to the [JetBrains Runtime Site](https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime) for general information and the latest build.
* Open the [Release notes](https://confluence.jetbrains.com/display/JBR/Release+notes) page to access all releases.
* Select the package name corresponding to the platform and SDK version.
@ -34,7 +33,7 @@ To acquire the compatible JetBrains Runtime:
* The version and build number match the JDK used to build the plugin project.
For example, `jbrx-8u252-osx-x64` matches the Java 8 JDK, build 252: `jdk-8u252-macosx-x64`.
* Pick the highest JetBrains Runtime build number available.
For example, as of this writing, the file is `jbrx-8u252-osx-x64-b1649.2.tar.gz`, meaning build 1649.2 for this JetBrains Runtime matching Java 8 JDK build 252.
For example, the file is `jbrx-8u252-osx-x64-b1649.2.tar.gz`, meaning build 1649.2 for this JetBrains Runtime matching Java 8 JDK build 252.
### Setting a JetBrains Runtime for Gradle-Based Plugin Projects
By default, the Gradle plugin will fetch and use the version of the JetBrains Runtime for the Development Instance corresponding to the version of the IntelliJ Platform used for building the plugin project.
@ -43,7 +42,7 @@ If required, an alternative version can be specified using `jbrVersion` attribut
### Setting a JetBrains Runtime for DevKit-Based Plugin Projects
The [Run Configuration](https://www.jetbrains.com/help/idea/run-debug-configuration.html) for a DevKit-based plugin project controls the JDK used to run and debug a plugin project in a Development Instance.
The default Run Configuration uses the same JDK for building the plugin project and running the plugin in a Development Instance.
To change the runtime for the Development Instance, set the _JRE_ field in the Run Configuration edit dialog to use a downloaded JetBrains Runtime.
To change the runtime for the Development Instance, set the _JRE_ field in the Run Configuration edit dialog to download a JetBrains Runtime.
## Enabling Auto-Reload

View File

@ -5,32 +5,43 @@ title: Indexing and PSI Stubs
## Indices
The indexing framework provides a quick way to locate certain elements, e.g. files containing a certain word or methods with a particular name, in large code bases. Plugin developers can use the existing indexes built by the IDE itself, as well as build and use their own indexes.
The indexing framework provides a quick way to locate specific elements, e.g., files containing a certain word or methods with a particular name, in large codebases.
Plugin developers can use the existing indexes built by the IDE itself and build and use their own indexes.
It supports two main types of indexes:
* [File-based indices](/basics/indexing_and_psi_stubs/file_based_indexes.md)
* [Stub indices](/basics/indexing_and_psi_stubs/stub_indexes.md)
File-based indexes are built directly over the content of files. Stub indexes are built over serialized *stub trees*. A stub tree for a source file is a subset of its PSI tree which contains only externally visible declarations and is serialized in a compact binary format.
File-based indexes are built directly over the content of files.
Stub indexes are built over serialized *stub trees*.
A stub tree for a source file is a subset of its PSI tree, which contains only externally visible declarations and is serialized in a compact binary format.
Querying a file-based index gets you the set of files matching a certain condition. Querying a stub index gets you the set of matching PSI elements. Therefore, custom language plugin developers should typically use stub indexes in their plugin implementations.
Querying a file-based index gets you the set of files matching a specific condition.
Querying a stub index gets you the set of matching PSI elements.
Therefore, custom language plugin developers should typically use stub indexes in their plugin implementations.
> **TIP** [Indices Viewer](https://plugins.jetbrains.com/plugin/13029-indices-viewer/) is a plugin that helps inspecting indices' contents and properties.
> **TIP** [Indices Viewer](https://plugins.jetbrains.com/plugin/13029-indices-viewer/) is a plugin that helps to inspect indices' contents and properties.
Please see also [Improving indexing performance](/reference_guide/performance/performance.md#improving-indexing-performance).
## Dumb Mode
Indexing is a potentially long process. It's performed in background, and during this time, IDE's features are restricted to the ones that don't require index: basic text editing, version control etc. This restriction is managed by [`DumbService`](upsource:///platform/core-api/src/com/intellij/openapi/project/DumbService.java).
Indexing is a potentially lengthy process.
It's performed in the background, and during this time, IDE's features are restricted to the ones that don't require index: basic text editing, version control, etc.
This restriction is managed by [`DumbService`](upsource:///platform/core-api/src/com/intellij/openapi/project/DumbService.java).
`DumbService` provides API to query whether the IDE is currently in "dumb" mode (where index access is not allowed) or "smart" mode (with all index built and ready to use). It also provides ways of delaying code execution until indices are ready. Please see its javadoc for more details.
`DumbService` provides API to query whether the IDE is currently in "dumb" mode (where index access is not allowed) or "smart" mode (with all index built and ready to use).
It also provides ways of delaying code execution until indices are ready.
Please see its JavaDoc for more details.
## Gists
Sometimes, the following conditions hold:
* the aggregation functionality of file-based indices is not needed. One just needs to calculate some data based on particular file's contents, and cache it on disk
* eagerly calculating the data for the entire project during indexing isn't needed (e.g. it slows down the indexing, and/or this data probably will ever be needed for a minor subset of all project files)
* the data can be recalculated lazily on request without major performance penalties
* the aggregation functionality of file-based indices is not needed.
One just needs to calculate some data based on a particular file's contents and cache it on disk.
* eagerly calculating the data for the entire project during indexing isn't needed (e.g., it slows down the indexing, and/or this data probably will ever be required for a minor subset of all project files).
* the data can be recalculated lazily on request without significant performance penalties.
In such cases, file-based index can be used, but file gists provide a way to perform data calculation lazily, caching on disk, and a more lightweight API. Please see [`VirtualFileGist`](upsource:///platform/indexing-api/src/com/intellij/util/gist/VirtualFileGist.java) and [`PsiFileGist`](upsource:///platform/indexing-api/src/com/intellij/util/gist/PsiFileGist.java) documentation.
A file-based index can be used in such cases, but file gists provide a way to perform data calculation lazily, caching on disk, and a more lightweight API.
Please see [`VirtualFileGist`](upsource:///platform/indexing-api/src/com/intellij/util/gist/VirtualFileGist.java) and [`PsiFileGist`](upsource:///platform/indexing-api/src/com/intellij/util/gist/PsiFileGist.java) documentation.

View File

@ -3,7 +3,8 @@ title: File-Based Indexes
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
File-based indexes are based on a Map/Reduce architecture. Each index has a specific type of key and a particular type of value.
File-based indexes are based on a Map/Reduce architecture.
Each index has a specific type of key and a particular type of value.
The key is what's later used to retrieve data from the index.
@ -11,19 +12,21 @@ The key is what's later used to retrieve data from the index.
The value is arbitrary data, which is associated with the key in the index.
*Example:* in the word index, the value is a mask indicating in which context the word occurs (code, string literal or comment).
*Example:* in the word index, the value is a mask indicating in which context the word occurs (code, string literal, or comment).
In the simplest case, when we only need to know in what files some data is present, the value has type `Void` and is not stored in the index.
When the index implementation indexes a file, it receives the content of a file and returns a map from the keys found in the file to the associated values.
When the index implementation indexes a file, it receives a file's content and returns a map from the keys found in the file to the associated values.
When you access the index, you specify the key you're interested in and get back the list of files in which the key occurs, and the value associated with each file.
## Implementing a File-Based Index
A relatively simple file-based index implementation is the [UI Designer bound forms index](upsource:///plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java). Refer to it as an example to understand this topic better.
A relatively simple file-based index implementation is the [UI Designer bound forms index](upsource:///plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java).
Refer to it as an example to understand this topic better.
Each specific index implementation is a class extending [`FileBasedIndexExtension`](upsource:///platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java). A file-based index should be registered in the `com.intellij.fileBasedIndex` extension point.
Each specific index implementation is a class extending [`FileBasedIndexExtension`](upsource:///platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java).
A file-based index should be registered in the `com.intellij.fileBasedIndex` extension point.
An implementation of a file-based index consists of the following main parts:
@ -33,11 +36,13 @@ An implementation of a file-based index consists of the following main parts:
Probably the most commonly used [`KeyDescriptor`](upsource:///platform/util/src/com/intellij/util/io/KeyDescriptor.java) implementation is [`EnumeratorStringDescriptor`](upsource:///platform/util/src/com/intellij/util/io/EnumeratorStringDescriptor.java), which is designed for storing efficiently storing identifiers.
* `getValueExternalizer()` returns the value serializer responsible for storing values in a serialized binary format.
* `getInputFilter()` allows restricting the indexing only to a certain set of files.
* `getVersion()` returns the version of the index implementation. The index is automatically rebuilt if the current version differs from the version of the index implementation used to build the index.
* `getVersion()` returns the version of the index implementation.
The index is automatically rebuilt if the current version differs from the version of the index implementation used to build it.
If you don't need to associate any value with the files (i.e., your value type is `Void`), you can simplify the implementation by using [`ScalarIndexExtension`](upsource:///platform/indexing-api/src/com/intellij/util/indexing/ScalarIndexExtension.java) as the base class.
> **WARNING** The data returned by `DataIndexer.map()` must depend only on input data passed to the method, and must not depend on any external files. Otherwise, your index will not be correctly updated when the external data changes, and you will have stale data in your index.
> **WARNING** The data returned by `DataIndexer.map()` must depend only on input data passed to the method, and must not depend on any external files.
> Otherwise, your index will not be correctly updated when the external data changes, and you will have stale data in your index.
> **NOTE** Please see `com.intellij.util.indexing.DebugAssertions` on how to enable additional debugging assertions during development to assert correct index implementation.
@ -52,14 +57,16 @@ The following primary operations are supported:
> **NOTE** The returned data is guaranteed to contain all keys found in up-to-date project content, but may also include additional keys not currently found in the project.
* `getValues()` allows to get all values associated with a specific key but not the files in which they were found.
* `getContainingFiles()` allows to collect all files in which a specific key was encountered.
* `processValues()` allows iterating though all files in which a specific key was encountered and accessing the associated values at the same time.
* `getContainingFiles()` allows collecting all files in which a particular key was encountered.
* `processValues()` allows iterating through all files in which a specific key was encountered and accessing the associated values simultaneously.
> **WARNING** Nested index access is forbidden as it might lead to a deadlock. Collect all necessary data from index A first, then process results while accessing index B.
> **WARNING** Nested index access is forbidden as it might lead to a deadlock.
> Collect all necessary data from index A first, then process results while accessing index B.
## Standard Indexes
The *IntelliJ Platform* contains several standard file-based indexes. The most useful indexes for plugin developers are:
The *IntelliJ Platform* contains several standard file-based indexes.
The most useful indexes for plugin developers are:
### Word Index

View File

@ -5,48 +5,69 @@ title: Stub Indexes
## Stub Trees
A stub tree is a subset of the PSI tree for a file; it is stored in a compact serialized binary format. The PSI tree for a file can be backed either by the AST (built by parsing the text of the file) or by the stub tree deserialized from disk. Switching between the two is transparent.
A stub tree is a subset of the PSI tree for a file; it is stored in a compact serialized binary format.
The PSI tree for a file can be backed either by the AST (built by parsing the file) or by the stub tree deserialized from disk.
Switching between the two is transparent.
The stub tree contains only a subset of the nodes. Typically it contains only the nodes that are needed to resolve the declarations contained in this file from external files. Trying to access any node which is not part of the stub tree, or to perform any operation which cannot be satisfied by the stub tree, e.g. accessing the text of a PSI element, causes file parsing and switches the PSI to AST backing.
The stub tree contains only a subset of the nodes.
Typically, it contains only the nodes needed to resolve the declarations contained in this file from external files.
Trying to access any node that is not part of the stub tree or perform any operation that cannot be satisfied by the stub tree, e.g., accessing the text of a PSI element, causes file parsing to switch from the PSI to AST backing.
Each stub in the stub tree is simply a bean class with no behavior. A stub stores a subset of the state of the corresponding PSI element, like element's name, modifier flags like public or final, etc. The stub also holds a pointer to its parent in the tree and a list of its children stubs.
Each stub in the stub tree is simply a bean class with no behavior.
A stub stores a subset of the corresponding PSI element's state, like the element's name, modifier flags like public or final, etc.
The stub also holds a pointer to its parent in the tree and a list of its children's stubs.
To support stubs for your custom language, you first need to decide which of the elements of your PSI tree should be stored as stubs. Typically you need to have stubs for things like methods or fields, which are visible from other files. You usually don't need to have stubs for things like statements or local variables, which are not visible externally.
To support stubs for your custom language, you first need to decide which of your PSI tree elements should be stored as stubs.
Typically, you need to have stubs for things like methods or fields visible from other files.
You usually don't need to have stubs for things like statements or local variables, which are not visible externally.
For each element type that you want to store in the stub tree, you need to perform the following steps:
* Define an interface for the stub, derived from the [`StubElement`](upsource:///platform/core-api/src/com/intellij/psi/stubs/StubElement.java) interface ([example](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertyStub.java)).
* Provide an implementation for the interface ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyStubImpl.java)).
* Make sure that the interface for the PSI element extends [`StubBasedPsiElement`](upsource:///platform/core-api/src/com/intellij/psi/StubBasedPsiElement.java) parameterized by the type of the stub interface ([example](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/Property.java)).
* Make sure that the implementation class for the PSI element extends [`StubBasedPsiElementBase`](upsource:///platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java) parameterized by the type of the stub interface ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java)). Provide both a constructor that accepts an `ASTNode` and a constructor which accepts a stub.
* Create a class which implements `IStubElementType` and is parameterized with the stub interface and the actual PSI element interface ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertyStubElementType.java)). Implement the `createPsi()` and `createStub()` methods for creating PSI from a stub and vice versa. Implement the `serialize()` and `deserialize()` methods for storing the data in a binary stream.
* Make sure the interface for the PSI element extends [`StubBasedPsiElement`](upsource:///platform/core-api/src/com/intellij/psi/StubBasedPsiElement.java) parameterized by the type of the stub interface ([example](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/Property.java)).
* Make sure the implementation class for the PSI element extends [`StubBasedPsiElementBase`](upsource:///platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java) parameterized by the type of the stub interface ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java)).
Provide both a constructor that accepts an `ASTNode` and a constructor that accepts a stub.
* Create a class that implements `IStubElementType` and is parameterized with the stub interface and the actual PSI element interface ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertyStubElementType.java)).
Implement the `createPsi()` and `createStub()` methods for creating PSI from a stub and vice versa.
Implement the `serialize()` and `deserialize()` methods for storing the data in a binary stream.
* Use the class implementing `IStubElementType` as the element type constant when parsing ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesElementTypes.java)).
* Make sure that all methods in the PSI element interface access the stub data rather than the PSI tree when appropriate ([example: `Property.getKey()` implementation](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java)).
* Make sure all methods in the PSI element interface access the stub data rather than the PSI tree when appropriate ([example: `Property.getKey()` implementation](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java)).
The following steps need to be performed only once for each language that supports stubs:
* Change the file element type for your language (the element type that you return from `ParserDefinition.getFileNodeType()`) to a class that extends [`IStubFileElementType`](upsource:///platform/core-impl/src/com/intellij/psi/tree/IStubFileElementType.java).
* In your `plugin.xml`, define the `com.intellij.stubElementTypeHolder` extension and specify the interface which contains the `IElementType` constants used by your language's parser as well as `externalIdPrefix` if possible ([example](upsource:///plugins/properties/src/META-INF/plugin.xml)).
For serializing string data, e.g. element names, in stubs, we recommend to use `StubOutputStream.writeName()` and `StubInputStream.readName()` methods. These methods ensure that each unique identifier is stored only once in the data stream. This reduces the size of the serialized stub tree data.
For serializing string data, e.g. element names, in stubs, we recommend to use `StubOutputStream.writeName()` and `StubInputStream.readName()` methods.
These methods ensure that each unique identifier is stored only once in the data stream.
This reduces the size of the serialized stub tree data.
If you need to change the stored binary format for the stubs (for example, if you want to store some additional data or some new elements), make sure that you advance the stub version returned from `IStubFileElementType.getStubVersion()` for your language. This will cause the stubs and stub indices to be rebuilt, and will avoid mismatches between the stored data format and the code trying to load it.
If you need to change the stored binary format for the stubs (for example, if you want to store some additional data or some new elements), make sure you advance the stub version returned from `IStubFileElementType.getStubVersion()` for your language.
This will cause the stubs and stub indices to be rebuilt, and will avoid mismatches between the stored data format, and the code trying to load it.
By default, if a PSI element extends `StubBasedPsiElement`, all elements of that type will be stored in the stub tree. If you need more precise control over which elements are stored, override `IStubElementType.shouldCreateStub()` and return `false` for elements which should not be included in the stub tree.
By default, if a PSI element extends `StubBasedPsiElement`, all elements of that type will be stored in the stub tree.
If you need more precise control over which elements are stored, override `IStubElementType.shouldCreateStub()` and return `false` for elements that should not be included in the stub tree.
> **NOTE** The exclusion is not recursive: if some elements of the element for which you returned false are also stub-based PSI elements, they will be included in the stub tree.
It's essential to make sure that all information stored in the stub tree depends only on the contents of the file for which stubs are being built, and does not depend on any external files. Otherwise the stub tree will not be rebuilt when an external dependency changes, and you will have stale and incorrect data in the stub tree.
It's essential to ensure that all information stored in the stub tree depends only on the contents of the file for which stubs are being built, and does not depend on any external files.
Otherwise, the stub tree will not be rebuilt when external dependency changes, and you will have stale and incorrect data in the stub tree.
> **TIP** Please see also [Improving indexing performance](/reference_guide/performance/performance.md#improving-indexing-performance).
## Stub Indexes
When building the stub tree, you can at the same time put some data about the stub elements into a number of indexes, which then can be used to find the PSI elements by the corresponding key. Unlike file-based indexes, stub indexes do not support storing custom data as values; the value is always a PSI element. Keys in stub indexes are normally strings (such as class names); other data types are also supported if desired.
When building the stub tree, you can, at the same time, put some data about the stub elements into a number of indexes, which then can be used to find the PSI elements by the corresponding key.
Unlike file-based indexes, stub indexes do not support storing custom data as values; the value is always a PSI element.
Keys in stub indexes are typically strings (such as class names); other data types are also supported if desired.
A stub index is a class which extends [`AbstractStubIndex`](upsource:///platform/indexing-api/src/com/intellij/psi/stubs/AbstractStubIndex.java). In the most common case, when the key type is `String`, you use a more specific base class, namely [`StringStubIndexExtension`](upsource:///platform/indexing-api/src/com/intellij/psi/stubs/StringStubIndexExtension.java). Stub index implementation classes are registered in the `com.intellij.stubIndex` extension point.
A stub index is a class which extends [`AbstractStubIndex`](upsource:///platform/indexing-api/src/com/intellij/psi/stubs/AbstractStubIndex.java).
In the most common case, when the key type is `String`, you use a more specific base class, namely [`StringStubIndexExtension`](upsource:///platform/indexing-api/src/com/intellij/psi/stubs/StringStubIndexExtension.java).
Stub index implementation classes are registered in the `com.intellij.stubIndex` extension point.
To put data into an index, you implement the method `IStubElementType.indexStub()` ([example: `JavaClassElementType.indexStub()`](upsource:///java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaClassElementType.java)). This method accepts an `IndexSink` as a parameter, and puts in the index ID and the key for each index in which the element should be stored.
To put data into an index, you implement the method `IStubElementType.indexStub()` ([example: `JavaClassElementType.indexStub()`](upsource:///java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaClassElementType.java)).
This method accepts an `IndexSink` as a parameter and puts in the index ID and the key for each index in which the element should be stored.
To access the data from an index, the following two methods are used:
@ -56,4 +77,3 @@ To access the data from an index, the following two methods are used:
## Related Forum Discussions
* [Lifecycle of stub creation](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206121959-Lifecycle-of-stub-creation/comments/206143885)

View File

@ -7,7 +7,8 @@ If you are writing code that you would like to contribute to the IntelliJ Platfo
## Following the Latest Source Code
If you submit patches, we strongly recommend building your patches against the latest version of the code from the Git repository. The easiest way to do so is to clone the JetBrains Git repository, track your work in Git, and create patches using the "git format-patch" command.
If you submit patches, we strongly recommend building your patches against the latest version of the code from the Git repository.
The easiest way to do so is to clone the JetBrains Git repository, track your work in Git, and create patches using the "git format-patch" command.
## General Architectural Principles
@ -15,7 +16,9 @@ Please do your best to follow common Java architectural principles. "Effective J
## Tests
Functional tests cover most of the existing functionality of IntelliJ IDEA. If tests cover the area you're modifying, you must run the tests and make sure that your changes do not introduce any new test failures. It's also strongly recommended that you provide new functional tests that cover the bugs you fix or the new features that you add.
Functional tests cover most of the existing functionality of IntelliJ IDEA.
If tests cover the area you're modifying, you must run the tests and make sure that your changes do not introduce any new test failures.
It's also strongly recommended that you provide new functional tests that cover the bugs you fix or the new features that you add.
## Code Formatting
@ -29,19 +32,25 @@ The easiest way to follow our code formatting guidelines is to reformat your cod
## Inspections
The IntelliJ IDEA Community Edition project includes a shared inspection profile. We strongly recommend making sure that the code you submit does not contain any warnings highlighted by the inspections configured in that inspection profile.
The IntelliJ IDEA Community Edition project includes a shared inspection profile.
We strongly recommend making sure that the code you submit does not contain any warnings highlighted by the inspections configured in that inspection profile.
## JavaDoc Comments
If your code adds new OpenAPI interfaces, classes, methods, or extension points, you must provide JavaDoc comments describing the parameters and intended usage of the APIs. Providing JavaDoc or other comments for other parts of the code is a good idea but isn't required.
If your code adds new OpenAPI interfaces, classes, methods, or extension points, you must provide JavaDoc comments describing the parameters and intended usage of the APIs.
Providing JavaDoc or other comments for other parts of the code is a good idea but isn't required.
## Commits
To avoid unnecessary work when reviewing your changes, please follow these guidelines:
- Look through all of your changes in your patch or pull request before you submit it to us. Make sure that everything you've changed is there for a reason.
- Please don't include unfinished work to the patch. Make sure that it doesn't contain any TODO comments. If you added some code and ended up not needing it, please make sure that you delete it before you submit your patch.
- Please don't include any changes that affect formatting, fixing "yellow code" (warnings), or code style along with actual changes that fix a bug or implement a feature. No one likes to leave poor code, but remember that having these changes mixed complicates the process of review.
- Look through all of your changes in your patch or pull request before you submit it to us.
Make sure that everything you've changed is there for a reason.
- Please don't include unfinished work to the patch.
Make sure that it doesn't contain any TODO comments.
If you added some code and ended up not needing it, please make sure that you delete it before you submit your patch.
- Please don't include any changes that affect formatting, fixing "yellow code" (warnings), or code style along with actual changes that fix a bug or implement a feature.
No one likes to leave poor code, but remember that having these changes mixed complicates the process of review.
- Please don't fix multiple problems within a single patch or pull request.
- Please don't commit your changes to configuration files (runConfigurations/IDEA.xml, codeStyleSettings.xml, misc.xml, etc.) unless it is essential for the fix itself.
- Please avoid moving or renaming classes unless it is necessary for the fix.

View File

@ -3,7 +3,7 @@ title: Persisting Sensitive Data
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
The Credentials Store API allows you to securely store sensitive user data, like passwords, server URLs, etc.
The Credentials Store API allows you to store sensitive user data securely, like passwords, server URLs, etc.
## How to Use
Use [`PasswordSafe`](upsource:///platform/platform-api/src/com/intellij/ide/passwordSafe/PasswordSafe.kt) to work with credentials.
@ -35,10 +35,10 @@ Use [`PasswordSafe`](upsource:///platform/platform-api/src/com/intellij/ide/pass
PasswordSafe.getInstance().set(credentialAttributes, credentials);
```
To remove stored credentials, pass `null` for `credentials` parameter.
To remove stored credentials, pass `null` for the `credentials` parameter.
## Storage
Default storage format depends on OS.
The default storage format depends on the OS.
| OS | Storage |
|---------|---------|

View File

@ -3,13 +3,16 @@ title: Persisting State of Components
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
The *IntelliJ Platform* provides an API that allows components or services to persist their state between restarts of the IDE. You can use either a simple API to persist a few values or persist the state of more complicated components using the [`PersistentStateComponent`](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) interface.
The *IntelliJ Platform* provides an API that allows components or services to persist their state between restarts of the IDE.
You can use either a simple API to persist a few values or persist the state of more complicated components using the [`PersistentStateComponent`](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) interface.
> **WARNING** If you need to persist sensitive data like passwords, please see [Persisting Sensitive Data](persisting_sensitive_data.md).
## Using PropertiesComponent for Simple Non-Roamable Persistence
If the plugin needs to persist just a few simple values, the easiest way to do so is to use the [`com.intellij.ide.util.PropertiesComponent`](upsource:///platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java) service. It can be used for saving both application-level values and project-level values (stored in the workspace file). Roaming is disabled for `PropertiesComponent`, so use it only for temporary, non-roamable properties.
If the plugin needs to persist just a few simple values, the easiest way to do so is to use the [`com.intellij.ide.util.PropertiesComponent`](upsource:///platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java) service.
It can save both application-level values and project-level values in the workspace file.
Roaming is disabled for `PropertiesComponent`, so use it only for temporary, non-roamable properties.
Use the `PropertiesComponent.getInstance()` method for storing application-level values, and the `PropertiesComponent.getInstance(Project)` method for storing project-level values.
@ -24,13 +27,15 @@ To use it:
- define the state class
- specify the storage location using `@com.intellij.openapi.components.State`
Note that instances of extensions cannot persist their state by implementing `PersistentStateComponent`. If your extension needs to have a persistent state, you need to define a separate service responsible for managing that state.
Note that instances of extensions cannot persist their state by implementing `PersistentStateComponent`.
If your extension needs to have a persistent state, you need to define a separate service responsible for managing that state.
### Implementing the PersistentStateComponent Interface
The implementation of `PersistentStateComponent` needs to be parameterized with the type of the state class. The state class can either be a separate JavaBean class, or the class implementing `PersistentStateComponent` itself.
The implementation of `PersistentStateComponent` needs to be parameterized with the type of state class.
The state class can either be a separate JavaBean class, or the class implementing `PersistentStateComponent`.
In the former case, the instance of the state class is typically stored as a field in the `PersistentStateComponent` class:
In the former case, the state class instance is typically stored as a field in the `PersistentStateComponent` class:
```java
@State(...)
@ -75,9 +80,11 @@ The implementation of `PersistentStateComponent` works by serializing public fie
To exclude a public field or bean property from serialization, annotate the field or getter with `@com.intellij.util.xmlb.annotations.Transient`.
Note that the state class must have a default constructor. It should return the default state of the component (one used if there is nothing persisted in the XML files yet).
Note that the state class must have a default constructor.
It should return the component's default state: the one used if there is nothing persisted in the XML files yet.
State class should have an `equals()` method, but if it is not implemented, state objects are compared by fields. When using Kotlin, use [Data Classes](https://kotlinlang.org/docs/reference/data-classes.html).
State class should have an `equals()` method, but state objects are compared by fields if it is not implemented.
When using Kotlin, use [Data Classes](https://kotlinlang.org/docs/reference/data-classes.html).
The following types of values can be persisted:
@ -119,12 +126,13 @@ class State {
### Defining the Storage Location
To specify where exactly the persisted values are stored, add `@State` annotation to the `PersistentStateComponent` class.
To specify where precisely the persisted values are stored, add `@State` annotation to the `PersistentStateComponent` class.
It has the following fields:
* `name` (required) — specifies the name of the state (name of the root tag in XML).
* `storages` — one or more of `@com.intellij.openapi.components.Storage` annotations to specify the storage locations. Optional for project-level values — standard project file is used in this case.
* `reloadable` (optional) — if set to false, complete project (or application) reload is required when the XML file is changed externally and the state has changed.
* `storages` — one or more of `@com.intellij.openapi.components.Storage` annotations to specify the storage locations.
Optional for project-level values — standard project file is used in this case.
* `reloadable` (optional) — if set to false, complete project (or application) reload is required when the XML file is changed externally, and the state has changed.
The simplest ways of specifying the `@Storage` annotation are as follows (since 2016.x; for previous versions, please see [old version](https://github.com/JetBrains/intellij-sdk-docs/blob/5dcb02991cf828a7d4680d125ce56b4c10234146/basics/persisting_state_of_components.md) of this document):
@ -132,40 +140,48 @@ The simplest ways of specifying the `@Storage` annotation are as follows (since
* `@Storage(StoragePathMacros.WORKSPACE_FILE)` for values stored in the workspace file.
By specifying a different value for the `value` parameter (`file` before 2016.x), the state is persisted in a different file.
The state is persisted in a separate file by specifying a different setting for the `value` parameter, which was the `file` parameter before 2016.x.
> **NOTE** For application-level components it is strongly recommended to use a custom file, using of `other.xml` is deprecated.
> **NOTE** For application-level components, it is strongly recommended to use a custom file, using of `other.xml` is deprecated.
The `roamingType` parameter of the `@Storage` annotation specifies the roaming type when the Settings Repository plugin is used.
## Customizing the XML Format of Persisted Values
> **NOTE** Please consider using annotation parameters only to achieve backward compatibility. Otherwise, please feel free to file issues about serialization cosmetics.
> **NOTE** Please consider using annotation parameters only to achieve backward compatibility.
> Otherwise, please feel free to file issues about serialization cosmetics.
If you want to use the default bean serialization but need to customize the storage format in XML (for example, for compatibility with previous versions of your plugin or externally defined XML formats), you can use the `@Tag`, `@Attribute`, `@Property`, `@MapAnnotation`, `@AbstractCollection` annotations.
Please see `com.intellij.util.xmlb.annotations`'s [`package.html`](upsource:///platform/util/src/com/intellij/util/xmlb/annotations/package.html) for more information.
If the state you need to serialize doesn't map cleanly to a JavaBean, you can use `org.jdom.Element` as the state class. In that case, you can use the `getState()` method to build an XML element with an arbitrary structure, which then is saved directly in the state XML file. In the `loadState()` method, you can deserialize the JDOM element tree using any custom logic. Please note this is not recommended and should be avoided whenever possible.
If the state you need to serialize doesn't map cleanly to a JavaBean, you can use `org.jdom.Element` as the state class.
In that case, you can use the `getState()` method to build an XML element with an arbitrary structure, which then is saved directly in the state XML file.
In the `loadState()` method, you can deserialize the JDOM element tree using any custom logic.
Please note this is not recommended and should be avoided whenever possible.
## Migrating Persisted Values
If the underlying persistence model or storage format has changed, a [`ConverterProvider`](upsource:///platform/lang-impl/src/com/intellij/conversion/ConverterProvider.java) can provide
[`ProjectConverter`](upsource:///platform/lang-impl/src/com/intellij/conversion/ProjectConverter.java) whose `getAdditionalAffectedFiles()` method returns affected files to migrate and performs programmatic migration of stored values.
If the underlying persistence model or storage format has changed, a [`ConverterProvider`](upsource:///platform/lang-impl/src/com/intellij/conversion/ConverterProvider.java) can provide [`ProjectConverter`](upsource:///platform/lang-impl/src/com/intellij/conversion/ProjectConverter.java) whose `getAdditionalAffectedFiles()` method returns affected files to migrate and performs programmatic migration of stored values.
## Persistent Component Lifecycle
The `loadState()` method is called after the component has been created (only if there is some non-default state persisted for the component), and after the XML file with the persisted state is changed externally (for example, if the project file was updated from the version control system). In the latter case, the component is responsible for updating the UI and other related components according to the changed state.
The `loadState()` method is called after the component has been created (only if there is some non-default state persisted for the component), and after the XML file with the persisted state is changed externally (for example, if the project file was updated from the version control system).
In the latter case, the component is responsible for updating the UI and other related components according to the changed state.
The `getState()` method is called every time the settings are saved (for example, on frame deactivation or when closing the IDE). If the state returned from `getState()` is equal to the default state (obtained by creating the state class with a default constructor), nothing is persisted in the XML. Otherwise, the returned state is serialized in XML and stored.
The `getState()` method is called every time the settings are saved (for example, on frame deactivation or when closing the IDE).
If the state returned from `getState()` is equal to the default state (obtained by creating the state class with a default constructor), nothing is persisted in the XML.
Otherwise, the returned state is serialized in XML and stored.
## Legacy API (JDOMExternalizable)
Older components use the [`JDOMExternalizable`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) interface for persisting state. It uses the `readExternal()` method for reading the state from a JDOM element, and `writeExternal()` to write the state to it.
Older components use the [`JDOMExternalizable`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) interface for persisting state.
It uses the `readExternal()` method for reading the state from a JDOM element, and `writeExternal()` to write the state.
Implementations can store the state in attributes and sub-elements manually, or use the [`DefaultJDOMExternalizer`](upsource:///platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java) class to store the values of all public fields automatically.
Implementations can manually store the state in attributes and sub-elements or use the [`DefaultJDOMExternalizer`](upsource:///platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java) class to store the values of all public fields automatically.
Components save their state in the following files:
* Project-level: project (`.ipr`) file. However, if the workspace option in the `plugin.xml` file is set to `true`, then workspace (`.iws`) file is used instead.
* Project-level: project (`.ipr`) file.
However, if the workspace option in the `plugin.xml` file is set to `true`, then the workspace (`.iws`) file is used instead.
* Module-level: module (`.iml`) file.

View File

@ -8,41 +8,59 @@ Please make sure to read the [Code of Conduct](/CODE_OF_CONDUCT.md).
## Participate in the Community
### Participate in Newsgroups and Forums
There are several community [forums and newsgroups](https://intellij-support.jetbrains.com/hc/en-us/community/topics) you can join to discuss the IntelliJ Platform. The forums are an excellent source for users and contributors interested in having technical discussions, answering questions, or resolving potential issues for newcomers.
There are several community [forums and newsgroups](https://intellij-support.jetbrains.com/hc/en-us/community/topics) you can join to discuss the IntelliJ Platform.
The forums are an excellent source for users and contributors interested in having technical discussions, answering questions, or resolving potential issues for newcomers.
### Link to jetbrains.org
The success of any open-source project depends on the number of people who use the product and contribute back to the project. By linking to jetbrains.org, you can increase the chances of a new user or contributor finding out about the project and joining the community.
The success of any open-source project depends on the number of people who use the product and contribute back to the project.
By linking to jetbrains.org, you can increase the chances of a new user or contributor finding out about the project and joining the community.
If you're as excited about IntelliJ IDEA Community Edition as we are, you can show it by linking to us. Project logos and other assets are [also available](https://www.jetbrains.com/company/press/).
If you're as excited about IntelliJ IDEA Community Edition as we are, you can show it by linking to us.
Project logos and other assets are [also available](https://www.jetbrains.com/company/press/).
### Promote IntelliJ Platform and IntelliJ IDEA Community Edition
Help promote the platform and IDE by using your blog, Twitter, Facebook, or submitting an article to your favorite local magazine. If you are a member of a different open-source community, why not mention IntelliJ IDEA on their discussion forums or at conferences? If you love IntelliJ IDEA, don't hold back - speak up! The more developers use IntelliJ IDEA, the more bugs will be caught, the more plugins will be written, the more visible the project, and the more benefits the community will get!
Help promote the platform and IDE by using your blog, Twitter, Facebook, or submitting an article to your favorite local magazine.
If you are a member of a different open-source community, why not mention IntelliJ IDEA on their discussion forums or at conferences? If you love IntelliJ IDEA, don't hold back - speak up! The more developers use IntelliJ IDEA, the more bugs will be caught, the more plugins will be written, the more visible the project, and the more benefits the community will get!
## Help Others Learn
### Write Documents
We're always looking for new articles about IntelliJ IDEA features as well as documentation for the IntelliJ Platform. You can write tutorials, how-tos, sample applications, or share your experience with the IntelliJ Platform. You can publish your documentation on a website or blog, or submit a [pull request](/CONTRIBUTING.md) to the SDK Docs.
We're always looking for new articles about IntelliJ IDEA features as well as documentation for the IntelliJ Platform.
You can write tutorials, how-tos, sample applications, or share your experience with the IntelliJ Platform.
You can publish your documentation on a website or blog, or submit a [pull request](/CONTRIBUTING.md) to the SDK Docs.
### Produce Screencasts
Screencasts have recently become very popular as a way to show other developers how to use the tool effectively. You can record a screencast about a particular feature or use case you discovered and would like to share it with the community.
Screencasts have recently become very popular as a way to show other developers how to use the tool effectively.
You can record a screencast about a particular feature or use case you discovered and would like to share it with the community.
## Contribute Code
### File a Bug Report
Bug reports take little time to file and are very helpful to developers. This is one of the easiest contributions you can make. When you discover a problem with the IDE or the platform, please report it. Make sure you provide information about your environment (OS, JDK version), steps to reproduce the issue, as well as a written description of the problem. You can file a bug in our [YouTrack issue tracker](https://youtrack.jetbrains.com/issues/IDEA).
Bug reports take little time to file and are very helpful to developers.
This is one of the easiest contributions you can make.
When you discover a problem with the IDE or the platform, please report it.
Make sure you provide information about your environment (OS, JDK version), steps to reproduce the issue, as well as a written description of the problem.
You can file a bug in our [YouTrack issue tracker](https://youtrack.jetbrains.com/issues/IDEA).
Before submitting an issue, please search for already submitted ones describing the same problem - and if you find one, feel free to vote for it.
### Help Triage Existing Bug Reports
Over the years, users have submitted thousands of issues to the IntelliJ issue tracker. Many of the unresolved issues are no longer applicable to the latest version of IntelliJ IDEA, are duplicates, or require additional information to be resolved. Leaving comments notifying about the status of such issues helps the team keep the issue tracker clean and useful for everyone.
Over the years, users have submitted thousands of issues to the IntelliJ issue tracker.
Many of the unresolved issues are no longer applicable to the latest version of IntelliJ IDEA, are duplicates, or require additional information to be resolved.
Leaving comments notifying about the status of such issues helps the team keep the issue tracker clean and useful for everyone.
### Write a Plugin
One of the best ways to contribute a larger piece of code, adding extra functionality to IntelliJ IDEA or any of the other IntelliJ Platform-based IDEs, is by writing a plugin. You can submit a plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com/), making it available for all users. When writing a plugin, you have control over the code and don't need to sign the contribution agreement.
One of the best ways to contribute a larger piece of code, adding extra functionality to IntelliJ IDEA or any of the other IntelliJ Platform-based IDEs, is by writing a plugin.
You can submit a plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com/), making it available for all users.
When writing a plugin, you have control over the code and don't need to sign the contribution agreement.
### Submit a Patch
If you would like to improve the code in the IntelliJ Platform or the core functionality of IntelliJ IDEA, you can submit a patch in the [YouTrack bug database](https://youtrack.jetbrains.com/issues/IDEA). You can either file a new issue with the patch attached or attach a patch to an issue submitted by another user. When writing a patch, please make sure to follow the [IntelliJ Platform Coding Guidelines](intellij_coding_guidelines.md).
If you would like to improve the code in the IntelliJ Platform or the core functionality of IntelliJ IDEA, you can submit a patch in the [YouTrack bug database](https://youtrack.jetbrains.com/issues/IDEA).
You can either file a new issue with the patch attached or attach a patch to an issue submitted by another user.
When writing a patch, please make sure to follow the [IntelliJ Platform Coding Guidelines](intellij_coding_guidelines.md).
Alternatively, you can fork the [IntelliJ IDEA Community Edition repository on GitHub](https://github.com/JetBrains/intellij-community), make the changes in your fork and send us a pull request.
A developer will review your patch and, if it meets the [quality criteria](intellij_coding_guidelines.md) and fits well with the rest of the code, you'll be notified about the acceptance of the patch. You will also need to sign the [JetBrains Contributor License Agreement (CLA)](https://www.jetbrains.com/agreements/cla/) to complete your contribution.
A developer will review your patch and, if it meets the [quality criteria](intellij_coding_guidelines.md) and fits well with the rest of the code, you'll be notified about the acceptance of the patch.
You will also need to sign the [JetBrains Contributor License Agreement (CLA)](https://www.jetbrains.com/agreements/cla/) to complete your contribution.
### Become a Committer
Developers with a long history of submitting high-quality patches can gain direct commit rights.

View File

@ -3,22 +3,22 @@ title: Dynamic Plugins
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
Starting with 2020.1 release, the ability to install, update and uninstall plugins without restarting the IDE is available in the IntelliJ Platform.
Starting with the 2020.1 release, installing, updating, and uninstalling plugins without restarting the IDE is available in the IntelliJ Platform.
During plugin development, [Auto-Reload](/basics/ide_development_instance.md#enabling-auto-reload) also allows code changes to take effect immediately in the sandbox IDE instance.
> **NOTE** If a plugin _requires_ restart (e.g., due to using native libraries) specify `require-restart="true"` for `<idea-plugin>` root tag in `plugin.xml`.
## Restrictions
For a plugin to support this, all restrictions listed below must be met. To verify a plugin locally, run _Plugin DevKit | Plugin descriptor | Plugin.xml dynamic plugin verification_
inspection on all plugin descriptor files (required `plugin.xml` as well as any additional files).
For a plugin to support this, all restrictions listed below must be met.
To verify a plugin locally, run **Analyize \| Run Inspection by Name... \| Plugin.xml dynamic plugin verification** inspection on all plugin descriptor files.
For plugins hosted on the [JetBrains Plugins Repository](https://plugins.jetbrains.com) the built-in [Plugin Verifier](https://blog.jetbrains.com/platform/2018/07/plugins-repository-now-integrates-with-the-plugin-verification-tool/)
will run these checks automatically. See [Plugin Verifier](/reference_guide/api_changes_list.md#plugin-verifier) for more information on how to run it locally.
For plugins hosted on the [JetBrains Plugins Repository](https://plugins.jetbrains.com) the built-in [Plugin Verifier](https://blog.jetbrains.com/platform/2018/07/plugins-repository-now-integrates-with-the-plugin-verification-tool/) will run these checks automatically.
See [Plugin Verifier](/reference_guide/api_changes_list.md#plugin-verifier) for more information on how to run it locally.
### No Use of Components
No Components must be used; existing ones [must be migrated](plugin_components.md) to services, extensions or listeners.
No Components must be used; existing ones [must be migrated](plugin_components.md) to services, extensions, or listeners.
### Action Group Requires ID
@ -26,13 +26,13 @@ All `<group>`s must declare a unique `id`.
### Use Only Dynamic Extensions
All extensions, whether defined in the platform itself or coming from other plugins, must be marked as dynamic (see next paragraph).
Whether defined in the platform itself or coming from other plugins, all extensions must be marked as dynamic (see next paragraph).
Some deprecated extension points (e.g., `com.intellij.configurationProducer`) are intentionally non-dynamic, and their usage should be migrated to the corresponding replacement.
### Mark Extension Points as Dynamic
All extension points provided by the plugin must adhere to specific usage rules and then [be declared](plugin_extension_points.md#dynamic-extension-points) ready for dynamic use explicitly.
The plugin's extension points must adhere to specific usage rules and then [be declared](plugin_extension_points.md#dynamic-extension-points) ready for dynamic use explicitly.
### Configurables Depending on Extension Points
@ -40,7 +40,7 @@ Any `Configurable` which depends on dynamic extension points must implement `Con
### No Use of Service Overrides
Application, project and module services declared with `overrides="true"` are not allowed.
Application, project, and module services declared with `overrides="true"` are not allowed.
## Code
@ -52,7 +52,7 @@ Loading/Unloading a plugin clears all cached values created using `CachedValuesM
### Do not Store PSI
Do not store references to PSI elements in objects which can survive plugin loading or unloading, use `SmartPsiElementPointer` instead.
Do not store references to PSI elements in objects which can survive plugin loading or unloading; use `SmartPsiElementPointer` instead.
### Do not Use FileType/Language as Map Key
@ -62,7 +62,7 @@ Replace with `String` from `Language.getID()`/`FileType.getName()`.
Register [`com.intellij.ide.plugins.DynamicPluginListener`](upsource:///platform/platform-impl/src/com/intellij/ide/plugins/DynamicPlugins.kt) [application listener](plugin_listeners.md) to receive updates on plugin load/unload events.
This can be used to e.g. cancel long-running activities or disallow unload due to ongoing processes.
This can be used to e.g., cancel long-running activities or disallow unload due to ongoing processes.
## Troubleshooting
@ -80,4 +80,5 @@ To find leaks preventing clean unload, perform the following steps:
- Verify that IDE runs with VM parameter `-XX:+UnlockDiagnosticVMOptions`
- Open the `.hprof` snapshot generated on plugin unload, look for the plugin ID string
- Find the `PluginClassLoader` referencing the plugin ID string
- Look at references to the `PluginClassLoader` instance. Every one of them is a memory leak (or part of a memory leak) that needs to be resolved.
- Look at references to the `PluginClassLoader` instance.
Every one of them is a memory leak (or part of a memory leak) that needs to be resolved.

View File

@ -6,10 +6,11 @@ title: Plugin Actions
The *IntelliJ Platform* provides the concept of _actions_.
An action is a class derived from [`AnAction`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java), whose `actionPerformed()` method is called when its menu item or toolbar button is selected.
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 **Help \| Find Action...** lookup.
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 the **Help \| Find Action...** lookup.
Actions are organized into groups, which, in turn, can contain other groups. A group of actions can form a toolbar or a menu.
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.
The user can customize all registered actions via [Menus and Toolbars](https://www.jetbrains.com/help/idea/customize-actions-menus-and-toolbars.html) settings.

View File

@ -3,9 +3,13 @@ title: Plugin Class Loaders
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
A separate class loader is used to load the classes of each plugin. This allows each plugin to use a different version of a library, even if the same library is used by the IDE itself or by another plugin.
A separate class loader is used to load the classes of each plugin.
This allows each plugin to use a different library version, even if the same library is used by the IDE itself or by another plugin.
By default, the main IDE class loader loads classes that were not found in the plugin class loader. However, in the `plugin.xml` file, you may use the `<depends>` element to specify that a [plugin depends](plugin_class_loaders.md) on one or more other plugins. In this case the class loaders of those plugins will be used for classes not found in the current plugin. This allows a plugin to reference classes from other plugins.
By default, the main IDE class loader loads classes were not found in the plugin class loader.
However, in the `plugin.xml` file, you may use the `<depends>` element to specify that a [plugin depends](plugin_class_loaders.md) on one or more other plugins.
In this case, the class loaders of those plugins will be used for classes not found in the current plugin.
This allows a plugin to reference classes from other plugins.
### Using ServiceLoader
Some libraries use [`ServiceLoader`](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/ServiceLoader.html) to detect and load implementations.

View File

@ -3,26 +3,24 @@ title: Plugin Components
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
> **WARNING** When writing new plugins, creating components should be avoided. Any existing components should be migrated to services, extensions, or listeners (see below).
> **WARNING** When writing new plugins, creating components should be avoided.
> Any existing components should be migrated to services, extensions, or listeners (see below).
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](dynamic_plugins.md) (the ability to install, update, and
uninstall plugins without restarting the IDE).
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](dynamic_plugins.md) (the ability to install, update, and uninstall plugins without restarting the IDE).
Plugin components are defined using `<application-components>`, `<project-components>`, and `<module-components>`
tags in a `plugin.xml` file.
Plugin components are defined using `<application-components>`, `<project-components>`, and `<module-components>` tags in a `plugin.xml` file.
## Migration
To migrate existing code from components to more modern APIs, please use the following guidelines:
* 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 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 a plugin. If this cannot be avoided, add a [listener](plugin_listeners.md) subscribing to the [AppLifecycleListener](upsource:///platform/platform-impl/src/com/intellij/ide/AppLifecycleListener.java) topic.
* 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. Alternatively, use `Disposer.register()` passing a `Project` or `Application` service instance
as the `parent` argument (see [Choosing a Disposable Parent](/basics/disposers.md#choosing-a-disposable-parent)).
* 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 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 a plugin.
If this cannot be avoided, add a [listener](plugin_listeners.md) subscribing to the [AppLifecycleListener](upsource:///platform/platform-impl/src/com/intellij/ide/AppLifecycleListener.java) topic.
* 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.
Alternatively, use `Disposer.register()` passing a `Project` or `Application` service instance as the `parent` argument (see [Choosing a Disposable Parent](/basics/disposers.md#choosing-a-disposable-parent)).

View File

@ -3,7 +3,8 @@ title: Plugin Configuration File - plugin.xml
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
The following is a sample plugin configuration file. This sample showcases and describes all elements that can be used in the `plugin.xml` file.
The following is a sample plugin configuration file.
This sample showcases and describes all elements that can be used in the `plugin.xml` file.
Additional information about configuring `<actions>` is available in the [Actions](/basics/action_system.md#registering-actions) section in Part II.
Limited HTML elements are allowed within `<description>` and `<change-notes>` elements.
@ -20,20 +21,20 @@ When using Gradle, a number of metadata elements will be provided at build time
Displayed in the "Plugins" settings dialog and the plugin repository Web interface. -->
<name>Vss Integration</name>
<!-- Unique identifier of the plugin. Should be FQN.
Cannot be changed between the plugin versions.
<!-- Unique identifier of the plugin. It should be FQN.
It cannot be changed between the plugin versions.
If not specified, <name> will be used (not recommended). -->
<id>com.jetbrains.vssintegration</id>
<!-- Description of the plugin.
Should be short and to the point.
Start the description with a verb in present simple form such as
Start the description with a verb in a present simple form such as
"integrates", "synchronizes", "adds support for" or "lets you view".
Dont use marketing adjectives like “simple”, “lightweight”, or “professional”.
Dont repeat the name of the plugin.
Don't use marketing adjectives like "simple", "lightweight", or "professional".
Don't repeat the name of the plugin.
For plugins that add language/platform/framework support, the description MUST specify
the version of the corresponding language/platform/framework.
Don't mention the IDE compatibility. E.g. don't say "Adds support to IntelliJ IDEA for..."
Don't mention the IDE compatibility. E.g., don't say "Adds support to IntelliJ IDEA for..."
Displayed in the "Plugins" settings dialog and the plugin repository Web interface.
Simple HTML elements can be included between <![CDATA[ ]]> tags. -->
<description>Integrates Volume Snapshot Service W10</description>
@ -57,7 +58,7 @@ When using Gradle, a number of metadata elements will be provided at build time
<!-- Mandatory dependencies on plugins or modules.
The FQN module names in <depends> elements are used to determine IDE compatibility for the plugin.
Include at least the module shown below to indicate compatibility with IntelliJ Platform-based products.
Also include dependencies on other plugins as needed.
Also, include dependencies on other plugins as needed.
See "Compatibility with Multiple Products" and "Plugin Dependencies" for more information. -->
<depends>com.intellij.modules.platform</depends>
<depends>com.third.party.plugin</depends>

View File

@ -7,7 +7,7 @@ A plugin may depend on classes from other plugins, either bundled, third-party,
This document describes the syntax for declaring plugin dependencies and optional plugin dependencies.
For more information about dependencies on the IntelliJ Platform modules, see Part II of this document: [Plugin Compatibility with IntelliJ Platform Products](/basics/getting_started/plugin_compatibility.md).
> **NOTE** It is not possible to specify the minimum/maximum version for the dependent plugin. ([Issue](https://youtrack.jetbrains.com/issue/IDEABKL-7906))
> **NOTE** It is impossible to specify the minimum/maximum version for the dependent plugin. ([Issue](https://youtrack.jetbrains.com/issue/IDEABKL-7906))
To express dependencies on classes from other plugins or modules, perform the following three required steps:
@ -27,7 +27,7 @@ Depending on the chosen development workflow (Gradle or DevKit), one of the two
### 2.1 Gradle
> **NOTE** Please see the `plugins` attribute [gradle-intellij-plugin: Configuration](https://github.com/JetBrains/gradle-intellij-plugin#configuration) for acceptable values.
If the project is using [Gradle](/tutorials/build_system.md) with a Groovy build script to build the plugin, add the dependency to the `plugins` parameter of the `intellij` block in your `build.gradle`, for example:
If the project uses [Gradle](/tutorials/build_system.md) with a Groovy build script to build the plugin, add the dependency to the `plugins` parameter of the `intellij` block in your `build.gradle`, for example:
```groovy
intellij {
@ -48,12 +48,11 @@ intellij {
### 2.2 DevKit
> **TIP** Existing DevKit-based projects can be converted to use [Gradle setup](/tutorials/build_system/prerequisites.md#adding-gradle-support-to-an-existing-devkit-based-intellij-platform-plugin) where managing dependencies is fully automated.
If the project is using [DevKit](/basics/getting_started/using_dev_kit.md), add the JARs of the plugin on which the project depends to the **classpath** of the *IntelliJ Platform SDK*.
If the project uses [DevKit](/basics/getting_started/using_dev_kit.md), add the JARs of the plugin on which the project depends to the **classpath** of the *IntelliJ Platform SDK*.
> **WARNING** Do not add the plugin JARs as a library: this will fail at runtime because the IntelliJ Platform will load two separate copies of the dependency plugin classes.
To do that, open the Project Structure dialog, select the SDK used in the project, press the + button in the Classpath tab, and
select the plugin JAR file or files:
To do that, open the Project Structure dialog, select the SDK used in the project, press the + button in the Classpath tab, and select the plugin JAR file or files:
* For bundled plugins, the plugin JAR files are located in `plugins/<pluginname>` or `plugins/<pluginname>/lib` under the main installation directory.
If you're not sure which JAR to add, you can add all of them.
* For non-bundled plugins, the plugin JAR files are located in `config/plugins/<pluginname>` or `config/plugins/<pluginname>/lib` under the directory specified as "Sandbox Home" in the IntelliJ Platform Plugin SDK settings.
@ -65,7 +64,7 @@ If only general IntelliJ Platform features (APIs) are used, then a default depen
To display a list of available IntelliJ Platform modules, invoke the [code completion](https://www.jetbrains.com/help/idea/auto-completing-code.html#4eac28ba) feature for the `<depends>` element contents while editing the plugin project's `plugin.xml` file.
### 3.1 Configuring plugin.xml
In the `plugin.xml`, add a `<depends>` tag with the ID of the dependency plugin as its content.
In the `plugin.xml`, add a `<depends>` tag with the dependency plugin's ID as its content.
Continuing with the example from [Section 2](#2-project-setup) above, the dependency declaration in `plugin.xml` would be:
```xml
@ -74,9 +73,9 @@ Continuing with the example from [Section 2](#2-project-setup) above, the depend
## Optional Plugin Dependencies
A project can also specify an optional plugin dependency. In this case, the plugin will load even if the plugin it depends on
is not installed or enabled, but part of the functionality of the plugin will not be available. In order to do that,
add `optional="true" config-file="otherconfig.xml"` to the `<depends>` tag.
A project can also specify an optional plugin dependency.
In this case, the plugin will load even if the plugin depends on is not installed or enabled, but part of the plugin's functionality will not be available.
In order to do that, add `optional="true" config-file="otherconfig.xml"` to the `<depends>` tag.
For example, if a plugin project adds additional highlighting for Java and Kotlin files, use the following setup.
The main `plugin.xml` will define an annotator for Java and specify an optional dependency on the Kotlin plugin:
@ -94,7 +93,8 @@ _plugin.xml_
</idea-plugin>
```
Then create a file called `withKotlin.xml`, in the same directory as the main `plugin.xml` file. In that file, define an annotator for Kotlin:
Then create a file called `withKotlin.xml`, in the same directory as the main `plugin.xml` file.
In that file, define an annotator for Kotlin:
_withKotlin.xml_

View File

@ -5,20 +5,21 @@ 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.
By defining _extension points_ in your plugin, you can allow other plugins to extend your plugin's functionality.
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.
* _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.
* _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 that will be turned into instances of that class.
## Declaring Extension Points
You can declare extensions and extension points in the plugin configuration file `plugin.xml`, within the `<extensions>` and `<extensionPoints>` sections, respectively.
You can declare extensions and extension points in the plugin configuration file `plugin.xml`, within the `<extensions>` and `<extensionPoints>` sections.
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.
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.
_myPlugin/META-INF/plugin.xml_
@ -37,12 +38,14 @@ _myPlugin/META-INF/plugin.xml_
</idea-plugin>
```
The `name` attribute assigns a unique name for this extension point, it will be prefixed with the plugin's `<id>` automatically.
The `name` attribute assigns a unique name for this extension point.
It will be prefixed with the plugin's `<id>` automatically.
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 `area` attribute determines the scope in which the extension will be instantiated. As extensions should be stateless, it is **not** recommended to use non-default.
The `area` attribute determines the scope in which the extension will be instantiated.
As extensions should be stateless, it is **not** recommended to use non-default.
Must be one of `IDEA_APPLICATION` for Application (default), `IDEA_PROJECT` for Project, or `IDEA_MODULE` for Module scope.
The plugin that contributes to the extension point will read those properties from the `plugin.xml` file.
@ -135,4 +138,5 @@ Extension points matching these conditions can then be marked as _dynamic_ by ad
</extensionPoints>
```
> **NOTE** All non-dynamic extension points are highlighted via _Plugin DevKit \| Plugin descriptor \| Plugin.xml dynamic plugin verification_ inspection available in IntelliJ IDEA 2020.1 or later. Previous versions also highlight `dynamic` attribute as "experimental".
> **NOTE** All non-dynamic extension points are highlighted via _Plugin DevKit \| Plugin descriptor \| Plugin.xml dynamic plugin verification_ inspection available in IntelliJ IDEA 2020.1 or later.
> Previous versions also highlight the `dynamic` attribute as "experimental".

View File

@ -5,8 +5,7 @@ redirect_from:
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
_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.
_Extensions_ are the most common way for a plugin to extend the IntelliJ Platform's functionality 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:
@ -17,17 +16,18 @@ The following are some of the most common tasks accomplished using extensions:
* [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.
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, Quick Documentation and other code insight features are available on extension point tags and attributes.
> **TIP** Auto-completion, Quick Documentation, and other code insight features are available on extension point tags and attributes.
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:
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.
* `{ID of a plugin}`, if your plugin extends the 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.
@ -85,13 +85,13 @@ Property name `language` (or ending in `*Language`, 2020.2+) resolves to all pre
Similarly, `action` resolves to all registered `<action>` IDs.
Specifying `@org.jetbrains.annotations.Nls` verifies capitalization of UI text properties according to given `capitalization` value (2019.2 and later).
Specifying `@org.jetbrains.annotations.Nls` validates a UI `String` capitalization according to the text property `Capitalization` enum value (2019.2 and later).
Attributes with `Enum` type support code insight with _lowerSnakeCased_ notation (2020.1 and later).
## How to get the extension points list?
All available extension points for the specified namespace can be listed by using auto-completion inside `<extensions>` block.
All available extension points for the specified namespace can be listed using auto-completion inside the `<extensions>` block.
To get a list of extension points available in the *IntelliJ Platform* core, consult the `<extensionPoints>` section of the following XML configuration files:
@ -102,4 +102,3 @@ To get a list of extension points available in the *IntelliJ Platform* core, con
- [`EditorExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/EditorExtensionPoints.xml)
- [`PlatformExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml)
- [`VcsExtensionPoints.xml`](upsource:///platform/vcs-impl/resources/META-INF/VcsExtensionPoints.xml)

View File

@ -57,7 +57,7 @@ Note the different areas of transparent padding used for each shape:
<br>
### Plugin Logo Colors
If the plugins technology already has a logo, use its colors.
If the plugin's technology already has a logo, use its colors.
Check the license terms before using the logo.
If there is no existing logo, or its use is prohibited, create a custom logo based on the [Action Colors Palette](https://jetbrains.design/intellij/principles/icons/#action-icons) in the IntelliJ Platform UI Guidelines for Icons.
@ -66,8 +66,8 @@ If there is no existing logo, or its use is prohibited, create a custom logo bas
| _The YouTrack Plugin Logo uses<br>the YouTrack product logo_ | _The Keymap Plugin Logo uses a color<br>from the Action Colors Palette_ |
Ensure a Plugin Logo is visible on both light and dark backgrounds.
If one Plugin Logo design does not work on both light and dark backgrounds, then create separate light and dark versions of the Plugin Logo.
The examples below illustrate how a Plugin Logo design may work well for a light background but not so well for a dark background.
If one Plugin Logo design does not work on both light and dark backgrounds, create separate light and dark versions of the Plugin Logo.
The examples below illustrate how a Plugin Logo design may work well for a light background but not for a dark background.
Consequently, a separate Plugin Logo for dark backgrounds is needed.
| ![Plugin Logo on Light UI Theme](img/light_version.png){:width="225px"} | ![Light Plugin Logo on Dark UI Theme](img/dark_bad.png){:width="225px"} | ![Plugin Logo for Dark UI Theme](img/dark_good.png){:width="225px"} |
@ -80,15 +80,16 @@ This vector image format is required because the Plugin Logo file must be small,
### Plugin Logo File Naming Convention
Name the Plugin Logo files according to the following conventions:
* `pluginIcon.svg` is the default Plugin Logo. If a separate Logo file for dark UI Themes exists in the plugin, then this file is used solely for light UI Themes,
* `pluginIcon.svg` is the default Plugin Logo.
If a separate Logo file for dark UI Themes exists in the plugin, then this file is used solely for light UI Themes,
* `pluginIcon_dark.svg` is an optional, alternative Plugin Logo for use solely with dark IDE UI Themes.
## Adding Plugin Logo Files to a Plugin Project
The Plugin Logo files must be in the `META-INF` folder of the plugin distribution file, i.e. the `*.jar` or `*.zip` file you upload to the plugin repository and install into a JetBrains IDE.
The Plugin Logo files must be in the `META-INF` folder of the plugin distribution file, i.e., the `*.jar` or `*.zip` file you upload to the plugin repository and install into a JetBrains IDE.
To include Plugin Logo files in your distribution file, place the Plugin Logo files into a plugin project's `resources/META-INF` folder.
Note that this requirement is the same regardless of using DevKit or Gradle for developing a plugin. For example:
Note that this requirement is the same regardless of using DevKit or Gradle for developing a plugin.
For example:
![Plugin Logo Files in META-INF folder](img/resource_directory_structure.png){:width="450px"}

View File

@ -11,9 +11,8 @@ _Listeners_ allow plugins to declaratively subscribe to events delivered through
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.
Declarative registration of listeners allows you to achieve better performance than registering listeners from code.
The advantage is because listener instances get created lazily - the first time an event is sent to the topic - and not during application startup or project opening.
## Defining Application-Level Listeners
@ -26,12 +25,10 @@ To define an application-level listener, add the following section to your `plug
```
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`](upsource:///platform/extensions/src/com/intellij/util/messages/Topic.java) instance for the type of events.
The `class` attribute specifies the class in your plugin that implements the listener interface and receives
the events.
Usually, this is the interface used as the type parameter of the [`Topic`](upsource:///platform/extensions/src/com/intellij/util/messages/Topic.java) 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`.
As a specific example, if you want to receive events about all virtual file system changes, 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
@ -43,8 +40,8 @@ messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListe
});
```
To use declarative registration, you no longer need to reference the `Topic` instance. Instead, you refer directly
to the listener interface class:
To use declarative registration, you no longer need to reference the `Topic` instance.
Instead, you refer directly to the listener interface class:
```xml
<applicationListeners>
@ -66,8 +63,8 @@ public class MyVfsListener implements BulkFileListener {
## 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:
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>
@ -76,8 +73,7 @@ Project-level listeners are registered in the same way, except that the top-leve
</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:
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 {
@ -100,4 +96,5 @@ Registration of listeners can be restricted using the following attributes:
- `os` - allows to restrict listener to given OS, e.g., `os="windows"` for Windows only (2020.1 and later)
- `activeInTestMode` - set to `false` to disable listener if `com.intellij.openapi.application.Application.isUnitTestMode()`==`true`
- `activeInHeadlessMode` - set to `false` to disable listener if `com.intellij.openapi.application.Application.isHeadlessEnvironment()`==`true`. Also covers `activeInTestMode` as test mode implies headless mode.
- `activeInHeadlessMode` - set to `false` to disable listener if `com.intellij.openapi.application.Application.isHeadlessEnvironment()`==`true`.
Also, covers `activeInTestMode` as test mode implies headless mode.

View File

@ -7,8 +7,8 @@ A _service_ is a plugin component loaded on demand when your plugin calls the `g
The *IntelliJ Platform* ensures that only one instance of a service is loaded even though it is called several times.
A service must have an implementation class which is used for service instantiation.
A service may also have an interface class which is used to obtain the service instance and provides API of the service.
A service must have an implementation class that is used for service instantiation.
A service may also have an interface class used to obtain the service instance and provide the service's API.
A service needing a shutdown hook/cleanup routine can implement [`Disposable`](upsource:///platform/util/src/com/intellij/openapi/Disposable.java) and perform necessary work in `dispose()` (see [Automatically Disposed Objects](/basics/disposers.md#automatically-disposed-objects)).
@ -16,13 +16,14 @@ A service needing a shutdown hook/cleanup routine can implement [`Disposable`](u
The *IntelliJ Platform* offers three types of services: _application level_ services (global singleton), _project level_ services, and _module level_ services.
For the latter two, a separate instance of the service is created for each instance of its corresponding scope, see [Project Model Introduction](/basics/project_structure.md).
> **NOTE** Please consider not using module level services because it can lead to increased memory usage for projects with many modules.
> **NOTE** Please consider not using module-level services because it can increase memory usage for projects with many modules.
#### Constructor
Project/Module level service constructors can have `Project`/`Module` argument.
Project/Module level service constructors can have a `Project`/`Module` argument.
To improve startup performance, avoid any heavy initializations in the constructor.
> **NOTE** Please note that using constructor injection is deprecated (and not supported in [Light Services](#light-services)) for performance reasons. Other dependencies should be [acquired only when needed](#retrieving-a-service) in all corresponding methods (see `someServiceMethod()` in [Project Service Sample](#project-service-sample)).
> **NOTE** Please note that using constructor injection is deprecated (and not supported in [Light Services](#light-services)) for performance reasons.
> Other dependencies should be [acquired only when needed](#retrieving-a-service) in all corresponding methods (see `someServiceMethod()` in [Project Service Sample](#project-service-sample)).
## Light Services
@ -30,7 +31,7 @@ To improve startup performance, avoid any heavy initializations in the construct
A service not going to be overridden does not need to be registered in `plugin.xml` (see [Declaring a Service](#declaring-a-service)).
Instead, annotate service class with [`@Service`](upsource:///platform/core-api/src/com/intellij/openapi/components/Service.java).
The service instance will be created in scope according to caller (see [Retrieving a Service](#retrieving-a-service)).
The service instance will be created in scope according to the caller (see [Retrieving a Service](#retrieving-a-service)).
Restrictions:
@ -54,7 +55,7 @@ Distinct extension points are provided for each type:
2. In the *New* menu, choose *Plugin DevKit* and click *Application Service*, *Project Service* or *Module Service* (not recommended, see Note above) depending on the type of service you need to use.
3. In the dialog box that opens, you can specify service interface and implementation, or just a service class if you uncheck *Separate interface from implementation* checkbox.
The IDE will generate new Java interface and class (or just a class if you unchecked *Separate interface from implementation* checkbox) and register the new service in `plugin.xml` file.
The IDE will generate a new Java interface and class (or just a class if you unchecked *Separate interface from implementation* checkbox) and register the new service in the `plugin.xml` file.
To clarify the service declaration procedure, consider the following fragment of the `plugin.xml` file:
@ -76,7 +77,8 @@ To provide custom implementation for test/headless environment, specify `testSer
## Retrieving a Service
Getting service doesn't need read action and can be performed from any thread. If service is requested from several threads, it will be initialized in the first thread, and other threads will be blocked until service is fully initialized.
Getting service doesn't need a read action and can be performed from any thread.
If service is requested from several threads, it will be initialized in the first thread, and other threads will be blocked until service is fully initialized.
To retrieve a service in Java code:
@ -119,7 +121,9 @@ _ProjectService.java_
## Sample Plugin
This sample plugin illustrates how to create and use a plugin service. This plugin has an application service counting the number of currently opened projects in the IDE. If this number exceeds the maximum allowed number of simultaneously opened projects, the plugin displays a warning message.
This sample plugin illustrates how to create and use a plugin service.
This plugin has an application service counting the number of currently opened projects in the IDE.
If this number exceeds the maximum number of simultaneously opened projects allowed by the plugin, it displays a warning message.
**To install and run the sample plugin**

View File

@ -12,14 +12,14 @@ The project structure and Java classes available to manage projects and modules
{:toc}
## Project and Its Components
This section briefly discusses the IDEA project structure, project components and related terms.
This section briefly discusses the IDEA project structure, project components, and related terms.
For more information about projects and their components, refer to [Project](https://www.jetbrains.com/help/idea/about-projects.html), [Module](https://www.jetbrains.com/help/idea/creating-and-managing-modules.html), [Library](https://www.jetbrains.com/help/idea/working-with-libraries.html), [Facet](https://www.jetbrains.com/help/idea/adding-support-for-frameworks-and-technologies.html#facets) in the IntelliJ IDEA Web Help.
### Project
In the IntelliJ Platform, a _project_ encapsulates all of a project's source code, libraries, and build instructions into a single organizational unit.
Everything done using the IntelliJ Platform SDK is done within the context of a project.
A project defines collections referred to as _modules_ and _libraries_.
Depending on the logical and functional requirements for the project, you can create a _single-module_ or a _multi-module_ project.
Depending on the project's logical and functional requirements, you can create a _single-module_ or a _multi-module_ project.
### Module
A _module_ is a discrete unit of functionality that can be run, tested, and debugged independently.
@ -30,14 +30,16 @@ A module can depend on other modules of the project.
### Library
A _library_ is an archive of compiled code (such as JAR files) on which modules depend.
The IntelliJ Platform supports three types of libraries:
* **Module Library**: the library classes are visible only in this module and the library information is recorded in the module's `.iml` file.
* **Project Library**: the library classes are visible within the project and the library information is recorded in the project's `.ipr` file or in `.idea/libraries`.
* **Global Library**: the library information is recorded in the `applicationLibraries.xml` file in the `~/.IntelliJIdea/config/options` directory. Global libraries are similar to project libraries, but are visible for different projects.
* **Module Library**: the library classes are visible only in this module, and the library information is recorded in the module's `.iml` file.
* **Project Library**: the library classes are visible within the project, and the library information is recorded in the project's `.ipr` file or in `.idea/libraries`.
* **Global Library**: the library information is recorded in the `applicationLibraries.xml` file in the `~/.IntelliJIdea/config/options` directory.
Global libraries are similar to project libraries but are visible for different projects.
For more information about libraries, refer to [Library](https://www.jetbrains.com/help/idea/working-with-libraries.html).
### SDK
Every project uses a Software Development Kit (_SDK_). For Java projects, SDK is referred to as JDK (Java Development Kit).
Every project uses a Software Development Kit (_SDK_).
For Java projects, SDK is referred to as JDK (Java Development Kit).
The SDK determines which API library is used to build the project.
If a project is multi-module, the project SDK is common for all modules within the project by default.
@ -48,7 +50,7 @@ For more information about SDKs, see [Working with SDKs](https://www.jetbrains.c
### Facet
A _facet_ represents a certain configuration, specific for a particular framework/technology associated with a module.
A module can have multiple facets.
E.g. Spring specific configuration is stored in a Spring facet.
E.g., Spring-specific configuration is stored in a Spring facet.
Facets are documented under [Facet](https://www.jetbrains.com/help/idea/adding-support-for-frameworks-and-technologies.html#facets) and [Language and Framework Specific Guidelines](https://www.jetbrains.com/help/idea/language-and-framework-specific-guidelines.html) in the IntelliJ IDEA Web Help.

View File

@ -3,7 +3,8 @@ title: PSI Cookbook
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
This page gives a list of recipes for the most common operations for working with the PSI (Program Structure Interface). Unlike [Developing Custom Language Plugins](/reference_guide/custom_language_support.md), it talks about working with the PSI of existing languages (such as Java).
This page gives recipes for the most common operations for working with the PSI (Program Structure Interface).
Unlike [Developing Custom Language Plugins](/reference_guide/custom_language_support.md), it talks about working with the PSI of existing languages (such as Java).
> **TIP** Please see also [Working with PSI efficiently](/reference_guide/performance/performance.md#working-with-psi-efficiently).

View File

@ -3,13 +3,15 @@ title: Run Configurations
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
*Run Configurations* allow users to run a certain type of external processes from within the IDE, e.g. a script, an application, a server, etc. You can provide UI for the user to specify execution options, as well as an option to create a run configuration based on a specific location in the source code.
*Run Configurations* allow users to run specific external processes from within the IDE, e.g., a script, an application, a server, etc.
You can provide the UI for the user to specify execution options, and an option to create a run configuration based on a specific location in the source code.
## Architectural Overview
Classes used to manipulate run configurations can be split into the following groups:
* [Run configuration management](/basics/run_configurations/run_configuration_management.md). This includes creation, persistence, and modification.
* [Run configuration management](/basics/run_configurations/run_configuration_management.md).
This includes creation, persistence, and modification.
* [Execution](/basics/run_configurations/run_configuration_execution.md).
This diagram shows the main classes:

View File

@ -6,47 +6,62 @@ title: Execution
The standard execution of a run action goes through the following steps:
* The user selects a *run configuration* (for example, by choosing one from the run configurations combobox) and an *executor* (for example, by pressing a toolbar button created by the executor).
* The *program runner* that will actually execute the process is selected, by polling all registered program runners and asking whether they can run the specified run profile with the specified executor ID.
* The [`ExecutionEnvironment`](upsource:///platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java) object is created. This object aggregates all the settings required to execute the process, as well as the selected [`ProgramRunner`](upsource:///platform/lang-api/src/com/intellij/execution/runners/ProgramRunner.java).
* The *program runner* that will actually execute the process is selected by polling all registered program runners and asking whether they can run the specified run profile with the specified executor ID.
* The [`ExecutionEnvironment`](upsource:///platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java) object is created.
This object aggregates all the settings required to execute the process and the selected [`ProgramRunner`](upsource:///platform/lang-api/src/com/intellij/execution/runners/ProgramRunner.java).
* `ProgramRunner.execute()` is called, receiving the executor and the execution environment.
Implementations of `ProgramRunner.execute()` go through the following steps to execute the process:
* `RunProfile.getState()` method is called to create a [`RunProfileState`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunProfileState.java) object, describing a process about to be started. At this stage, the command line parameters, environment variables and other information required to start the process is initialized.
* `RunProfileState.execute()` is called. It starts the process, attaches a `ProcessHandler` to its input and output streams, creates a console to display the process output, and returns an [`ExecutionResult`](upsource:///platform/lang-api/src/com/intellij/execution/ExecutionResult.java) object aggregating the console and the process handler.
* `RunProfile.getState()` method is called to create a [`RunProfileState`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunProfileState.java) object, describing a process about to be started.
At this stage, the command line parameters, environment variables, and other information required to start the process are initialized.
* `RunProfileState.execute()` is called.
It starts the process, attaches a `ProcessHandler` to its input and output streams, creates a console to display the process output, and returns an [`ExecutionResult`](upsource:///platform/lang-api/src/com/intellij/execution/ExecutionResult.java) object aggregating the console and the process handler.
* The `RunContentBuilder` object is created and invoked to display the execution console in a tab of the Run or Debug tool window.
## Executor
The [`Executor`](upsource:///platform/lang-api/src/com/intellij/execution/Executor.java) interface describes a specific way of executing any possible run configuration.
The three default executors provided by the *IntelliJ Platform* by default are _Run_, _Debug_ and _Run with Coverage_. Each executor gets its own toolbar button, which starts the selected run configuration using this executor, and its own context menu item for starting a configuration using this executor.
The three default executors provided by the *IntelliJ Platform* by default are _Run_, _Debug_, and _Run with Coverage_. Each executor gets its own toolbar button, which starts the selected run configuration using this executor, and its own context menu item for starting a configuration using this executor.
As a plugin developer, you normally don't need to implement the `Executor` interface. However, it can be useful, for example, if you're implementing a profiler integration and want to provide the possibility to execute any configuration with profiling.
As a plugin developer, you usually don't need to implement the `Executor` interface.
However, it can be useful, for example, if you're implementing a profiler integration and want to provide the possibility to execute any configuration with profiling.
## Running a Process
The `RunProfileState` interface comes up in every run configuration implementation as the return value `RunProfile.getState()`. It describes a process which is ready to be started and holds the information like the command line, current working directory, and environment variables for the process to be started. (The existence of `RunProfileState` as a separate step in the execution flow allows run configuration extensions and other components to patch the configuration and to modify the parameters before it gets executed.)
The `RunProfileState` interface comes up in every run configuration implementation as the return value `RunProfile.getState()`.
It describes a process that is ready to be started and holds information like the command line, current working directory, and environment variables for the process to be started. (The existence of `RunProfileState` as a separate step in the execution flow allows run configuration extensions and other components to patch the configuration and modify the parameters before it gets executed.)
The standard base class used as implementation of `RunProfileState` is [`CommandLineState`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java). It contains the logic for putting together a running process and a console into an [`ExecutionResult`](upsource:///platform/lang-api/src/com/intellij/execution/ExecutionResult.java), but doesn't know anything how the process is actually started. For starting the process, it's best to use the [`GeneralCommandLine`](upsource:///platform/platform-util-io/src/com/intellij/execution/configurations/GeneralCommandLine.java) class, which takes care of setting up the command line parameters and executing the process.
The standard base class used as implementation of `RunProfileState` is [`CommandLineState`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java).
It contains the logic for putting together a running process and a console into an [`ExecutionResult`](upsource:///platform/lang-api/src/com/intellij/execution/ExecutionResult.java), but doesn't know anything how the process is actually started.
For starting the process, it's best to use the [`GeneralCommandLine`](upsource:///platform/platform-util-io/src/com/intellij/execution/configurations/GeneralCommandLine.java) class, which takes care of setting up the command line parameters and executing the process.
Alternatively, if the process you need to run is a JVM-based one, you can use the [`JavaCommandLineState`](upsource:///java/execution/openapi/src/com/intellij/execution/configurations/JavaCommandLineState.java) base class. It knows about the command line parameters of the JVM and can take care of details like calculating the classpath for the JVM.
Alternatively, if the process you need to run is a JVM-based one, you can use the [`JavaCommandLineState`](upsource:///java/execution/openapi/src/com/intellij/execution/configurations/JavaCommandLineState.java) base class.
It knows about the JVM command line parameters and can take care of details like calculating the classpath for the JVM.
To monitor the execution of a process and capture its output, the [`OSProcessHandler`](upsource:///platform/platform-util-io/src/com/intellij/execution/process/OSProcessHandler.java) class is normally used. Once you've created an instance of `OSProcessHandler` from either a command line or a Process object, you need to call the `startNotify()` method to start capturing its output. You may also want to attach a [`ProcessTerminatedListener`](upsource:///platform/platform-api/src/com/intellij/execution/process/ProcessTerminatedListener.java) to the `OSProcessHandler`, so that the exit status of the process will be displayed in the console.
To monitor the execution of a process and capture its output, the [`OSProcessHandler`](upsource:///platform/platform-util-io/src/com/intellij/execution/process/OSProcessHandler.java) class is usually used.
Once you've created an instance of `OSProcessHandler` from either a command line or a Process object, you need to call the `startNotify()` method to capture its output.
You may also want to attach a [`ProcessTerminatedListener`](upsource:///platform/platform-api/src/com/intellij/execution/process/ProcessTerminatedListener.java) to the `OSProcessHandler` so that the exit status of the process will be displayed in the console.
## Displaying Process Output
If you're using `CommandLineState`, a console view will be automatically created and attached to the output of the process. Alternatively, you can arrange this yourself:
If you're using `CommandLineState`, a console view will be automatically created and attached to the process's output.
Alternatively, you can arrange this yourself:
* `TextConsoleBuilderFactory.createBuilder(project).getConsole()` creates a [`ConsoleView`](upsource:///platform/lang-api/src/com/intellij/execution/ui/ConsoleView.java) instance
* `ConsoleView.attachToProcess()` attaches it to the output of a process.
If the process you're running uses ANSI escape codes to color its output, the [`ColoredProcessHandler`](upsource:///platform/platform-impl/src/com/intellij/execution/process/ColoredProcessHandler.java) class will parse it and display the colors in the IntelliJ console.
If the running process uses ANSI escape codes to color its output, the [`ColoredProcessHandler`](upsource:///platform/platform-impl/src/com/intellij/execution/process/ColoredProcessHandler.java) class will parse it and display the colors in the IntelliJ console.
Console [filters](upsource:///platform/lang-api/src/com/intellij/execution/filters/Filter.java) allow you to convert certain strings found in the process output to clickable hyperlinks. To attach a filter to the console, use `CommandLineState.addConsoleFilters()` or, if you're creating a console manually, `TextConsoleBuilder.addFilter()`.
Console [filters](upsource:///platform/lang-api/src/com/intellij/execution/filters/Filter.java) allow you to convert certain strings found in the process output to clickable hyperlinks.
To attach a filter to the console, use `CommandLineState.addConsoleFilters()` or, if you're creating a console manually, `TextConsoleBuilder.addFilter()`.
Two common filter implementations you may want to reuse are [`RegexpFilter`](upsource:///platform/lang-api/src/com/intellij/execution/filters/RegexpFilter.java) and [`UrlFilter`](upsource:///platform/lang-api/src/com/intellij/execution/filters/UrlFilter.java).
## Starting a Run Configuration from Code
If you have an existing run configuration that you need to execute, the easiest way to do so is to use [`ProgramRunnerUtil.executeConfiguration()`](upsource:///platform/execution-impl/src/com/intellij/execution/ProgramRunnerUtil.java). The method takes a [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java), a [`RunnerAndConfigurationSettings`](upsource:///platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java), as well as an [`Executor`](upsource:///platform/lang-api/src/com/intellij/execution/Executor.java). To get the `RunnerAndConfigurationSettings` for an existing configuration, you can use, for example, `RunManager.getConfigurationSettings(ConfigurationType)`. As the last parameter, you normally pass either `DefaultRunExecutor.getRunExecutorInstance()` or `DefaultDebugExecutor.getDebugExecutorInstance()`.
If you have an existing run configuration that you need to execute, the easiest way to do so is to use [`ProgramRunnerUtil.executeConfiguration()`](upsource:///platform/execution-impl/src/com/intellij/execution/ProgramRunnerUtil.java).
The method takes a [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java), a [`RunnerAndConfigurationSettings`](upsource:///platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java), as well as an [`Executor`](upsource:///platform/lang-api/src/com/intellij/execution/Executor.java).
To get the `RunnerAndConfigurationSettings` for an existing configuration, you can use, for example, `RunManager.getConfigurationSettings(ConfigurationType)`.
As the last parameter, you normally pass either `DefaultRunExecutor.getRunExecutorInstance()` or `DefaultDebugExecutor.getDebugExecutorInstance()`.

View File

@ -3,14 +3,15 @@ title: Run Configuration Management
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
This document describes main classes to work with run configurations and common use case.
This document describes the primary classes to work with run configurations and everyday use cases.
* Dummy table of contents
{:toc}
## Configuration Type
The starting point for implementing any run configuration type is the [`ConfigurationType`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationType.java) interface. The list of available configuration types is shown when a user opens the _'Edit run configurations'_ dialog and executes _'Add'_ action:
The starting point for implementing any run configuration type is the [`ConfigurationType`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationType.java) interface.
The list of available configuration types is shown when a user opens the _'Edit run configurations'_ dialog and executes _'Add'_ action:
![Create](/basics/img/create-1.png)
@ -20,39 +21,47 @@ Every type there is represented as an instance of [`ConfigurationType`](upsource
<configurationType implementation="org.jetbrains.plugins.gradle.service.execution.GradleExternalTaskConfigurationType" />
```
The easiest way to implement this interface is to use the [`ConfigurationTypeBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/runConfigurationType.kt) base class. In order to use it, you need to inherit from it and to provide the configuration type parameters (ID, name, description and icon) as constructor parameters. In addition to that, you need to call the [`addFactory()`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/runConfigurationType.kt) method to add a configuration factory.
The easiest way to implement this interface is to use the [`ConfigurationTypeBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/runConfigurationType.kt) base class.
To use it, you need to inherit from it and to provide the configuration type parameters (ID, name, description, and icon) as constructor parameters.
In addition to that, you need to call the [`addFactory()`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/runConfigurationType.kt) method to add a configuration factory.
## Configuration Factory
All run configurations are created by the [`ConfigurationFactory`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) registered for a particular `ConfigurationType`. It's possible that one `ConfigurationType` [has more than one](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationType.java) `ConfigurationFactory`:
All run configurations are created by the [`ConfigurationFactory`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) registered for a particular `ConfigurationType`.
It's possible that one `ConfigurationType` [has more than one](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationType.java) `ConfigurationFactory`:
![Configuration Factory](/basics/img/create-3.png)
The key API of [`ConfigurationFactory`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java), and the only method that you're required to implement, is the [`createTemplateConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) method. This method is called once per project to create the template run configuration.
The key API of [`ConfigurationFactory`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java), and the only method that you're required to implement, is the [`createTemplateConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) method.
This method is called once per project to create the template run configuration.
All real run configurations (loaded from the workspace or created by the user) are called by cloning the template through the [`createConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) method.
You can customize additional aspects of your configuration factory by overriding the [`getIcon`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java), [`getAddIcon`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java)<!--#L55-->, [`getName`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java)<!--#L51--> and the default settings methods. These additional overrides are optional.
You can customize additional aspects of your configuration factory by overriding the [`getIcon`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java), [`getAddIcon`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java)<!--#L55-->, [`getName`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java)<!--#L51--> and the default settings methods.
These additional overrides are optional.
## Run Configuration
The run configuration itself is represented by the [`RunConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java) interface. A _'run configuration'_ here is some named profile which can be executed, e.g. application started via `main()` class, test, remote debug to particular machine/port etc.
The run configuration itself is represented by the [`RunConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java) interface.
A _'run configuration'_ here is some named profile which can be executed, e.g., the application started via `main()` class, test, remote debug to particular machine/port, etc.
Here is an example of a Java run configurations defined for a particular project:
Here is an example of a Java run configuration defined for a particular project:
![Run Configuration](/basics/img/create-2.png)
When implementing a run configuration, you may want to use one of the common base classes:
* [`RunConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java) is a general-purpose superclass that contains the most basic implementation of a run configuration.
* [`LocatableConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/LocatableConfigurationBase.java) is a common base class that should be used for configurations that can be created from context by a `RunConfigurationProducer`. It supports automatically generating a name for a configuration from its settings and keeping track of whether the name was changed by the user.
* [`LocatableConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/LocatableConfigurationBase.java) is a common base class that should be used for configurations that can be created from context by a `RunConfigurationProducer`.
It supports automatically generating a name for a configuration from its settings and keeping track of whether the name was changed by the user.
* [`ModuleBasedConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ModuleBasedConfiguration.java) is a base class for a configuration that is associated with a specific module (for example, Java run configurations use the selected module to determine the run classpath).
## Settings Editor
That common run configuration settings might be modified via:
[`RunConfiguration`-specific UI](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java). That is handled by [`SettingsEditor`](upsource:///platform/platform-api/src/com/intellij/openapi/options/SettingsEditor.java)<!--#L97-->:
[`RunConfiguration`-specific UI](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java).
That is handled by [`SettingsEditor`](upsource:///platform/platform-api/src/com/intellij/openapi/options/SettingsEditor.java)<!--#L97-->:
* [`getComponent()`](upsource:///platform/platform-api/src/com/intellij/openapi/options/SettingsEditor.java) method is called by the IDE and shows run configuration specific UI.
* [`resetFrom()`](upsource:///platform/platform-api/src/com/intellij/openapi/options/SettingsEditor.java) is called to discard all non-confirmed user changes made via that UI.
@ -60,35 +69,41 @@ That common run configuration settings might be modified via:
## Persistence
That run configuration settings are persistent, i.e. they are stored at file system and loaded back on the IDE startup. That is performed via [`writeExternal()`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) and [`readExternal()`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java)<!--#L26--> methods of [`RunConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java) class correspondingly.
That run configuration settings are persistent, i.e., they are stored at the file system and loaded back on the IDE startup.
That is performed via [`writeExternal()`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) and [`readExternal()`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java)<!--#L26--> methods of [`RunConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java) class correspondingly.
The actual configurations stored by the *IntelliJ Platform* are represented by instances of the [`RunnerAndConfigurationSettings`](upsource:///platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java) class, which combines a run configuration with runner-specific settings, as well as keeping track of certain run configuration flags such as "temporary" or "singleton".
Dealing with instances of this class becomes necessary when you need to create run configurations from code. This is accomplished with the following two steps:
Dealing with instances of this class becomes necessary when you need to create run configurations from code.
This is accomplished with the following two steps:
* `RunManager.createConfiguration()` creates an instance of `RunnerAndConfigurationSettings`.
* `RunManager.addConfiguration()` makes it persistent by adding it to either the list of shared configurations stored in a project, or to the list of local configurations stored in the workspace file.
* `RunManager.addConfiguration()` makes it persistent by adding it to either the list of shared configurations stored in a project or to the list of local configurations stored in the workspace file.
## Refactoring Support
Most run configurations contain references to classes, files or directories in their settings, and these settings usually need to be updated when the corresponding element is renamed or moved.
Most run configurations contain references to classes, files, or directories in their settings, and these settings usually need to be updated when the corresponding element is renamed or moved.
In order to support that, your run configuration needs to implement the [`RefactoringListenerProvider`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RefactoringListenerProvider.java) interface.
To support that, your run configuration needs to implement the [`RefactoringListenerProvider`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RefactoringListenerProvider.java) interface.
In your implementation of `getRefactoringElementListener()`, you need to check whether the element being refactored is the one that your run configuration refers to, and if it is, you return a [`RefactoringElementListener`](upsource:///platform/analysis-api/src/com/intellij/refactoring/listeners/RefactoringElementListener.java) that updates your configuration according to the new name and location of the element.
In your implementation of `getRefactoringElementListener()`, you need to check whether the refactored element is the one that your run configuration refers to.
If it is, you return a [`RefactoringElementListener`](upsource:///platform/analysis-api/src/com/intellij/refactoring/listeners/RefactoringElementListener.java) that updates your configuration according to the new name and location of the element.
## Creating Configurations from Context
Many plugins support automatic creation of run configurations from context, so that the user can click, for example, on an application or test class and automatically run it using the correct run configuration type. In order to support that, you need to provide an implementation of the [`RunConfigurationProducer`](upsource:///platform/lang-api/src/com/intellij/execution/actions/RunConfigurationProducer.java)
interface and to register it as `<runConfigurationProducer>` in your `plugin.xml`. (Note that this API has been redesigned in IntelliJ IDEA 13; the old [`RuntimeConfigurationProducer`](upsource:///platform/lang-api/src/com/intellij/execution/junit/RuntimeConfigurationProducer.java) is a much more confusing version of the same API).
Many plugins support automatic creation of run configurations from context so that the user can click, for example, on an application or test class and automatically run it using the correct run configuration type.
To support that, you need to provide an implementation of the [`RunConfigurationProducer`](upsource:///platform/lang-api/src/com/intellij/execution/actions/RunConfigurationProducer.java) interface and to register it as `<runConfigurationProducer>` in your `plugin.xml`.
This API was redesigned in IntelliJ IDEA 13; the previous [`RuntimeConfigurationProducer`](upsource:///platform/lang-api/src/com/intellij/execution/junit/RuntimeConfigurationProducer.java) is a much more confusing version of the same API.
The two main methods that you need to implement are:
* `setupConfigurationFromContext()` receives a blank configuration of your type and a `ConfigurationContext` containing information about a source code location (accessible by calling `getLocation()` or `getPsiLocation()`). Your implementation needs to check whether the location is applicable for your configuration type (for example, if it's in a file of the language you're supporting). If not, you need to return false, and if it is, you need to put the correct context-specific settings into the run configuration and return true.
* `isConfigurationFromContext()` checks if the specified configuration of your type was created from the specified context. Implementing this method allows you to reuse an existing run configuration which is applicable to the current context instead of creating a new one and possibly ignoring the customisations the user has performed in the existing one.
* `setupConfigurationFromContext()` receives a blank configuration of your type and a `ConfigurationContext` containing information about a source code location (accessible by calling `getLocation()` or `getPsiLocation()`).
Your implementation needs to check whether the location is applicable for your configuration type (for example, if it's in a file of the language you're supporting).
If not, you need to return false, and if it is, you need to put the correct context-specific settings into the run configuration and return true.
* `isConfigurationFromContext()` checks if your type's specified configuration was created from the specified context.
Implementing this method allows you to reuse an existing run configuration, which applies to the current context instead of creating a new one and possibly ignoring the user's customizations in the existing one.
Note that, in order to support automatic naming of configurations created from context, your configuration should use
[`LocatableConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/LocatableConfigurationBase.java) as the base class.
Note that, to support the automatic naming of configurations created from context, your configuration should use [`LocatableConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/LocatableConfigurationBase.java) as the base class.
## Running from the Gutter

View File

@ -9,4 +9,3 @@ For more information, see:
* [Settings Guide](/reference_guide/settings_guide.md) for information about Settings Extension Points and implementations.
* [Custom Settings Groups](/reference_guide/settings_groups.md) for information about creating custom Settings groups and parent-child relationships.
* [Settings Tutorial](/tutorials/settings_tutorial.md) for step-by-step instructions for creating a simple set of custom Settings.

View File

@ -3,9 +3,10 @@ title: Light and Heavy Tests
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
Plugin tests run in a real, rather than mocked, *IntelliJ Platform* environment and use real implementations for most of the application and project components/services.
Plugin tests run in a real, rather than mocked, *IntelliJ Platform* environment and use real implementations for most application and project components/services.
Loading and initializing all the project components and services for a project to run tests is a quite expensive operation, and we want to avoid doing it for each test. Dependently on the loading and execution time, we make a difference between *heavy* tests and *light* tests available in *IntelliJ Platform* test framework:
Loading and initializing all the project components and services for a project to run tests is a relatively expensive operation, and we want to avoid doing it for each test.
Dependently on the loading and execution time, we make a difference between *heavy* tests and *light* tests available in *IntelliJ Platform* test framework:
* *Heavy* tests create a new project for each test.
* *Light* tests reuse a project from the previous test run when possible.
@ -23,7 +24,8 @@ The standard way of writing a light test is to extend the following classes:
> **NOTE** In 2019.2, `LightPlatformCodeInsightFixtureTestCase` has been renamed to `BasePlatformTestCase` and `LightCodeInsightFixtureTestCase` to `LightJavaCodeInsightFixtureTestCase` respectively.
When writing a light test, you can specify the requirements for the project that you need to have in your test, such as the module type, the configured SDK, facets, libraries, etc. You do so by extending the [`LightProjectDescriptor`](upsource:///platform/testFramework/src/com/intellij/testFramework/LightProjectDescriptor.java) class and returning your project descriptor from `getProjectDescriptor()`.
When writing a light test, you can specify the project's requirements that you need to have in your test, such as the module type, the configured SDK, facets, libraries, etc.
You do so by extending the [`LightProjectDescriptor`](upsource:///platform/testFramework/src/com/intellij/testFramework/LightProjectDescriptor.java) class and returning your project descriptor from `getProjectDescriptor()`.
Before executing each test, the project will be reused if the test case returns the same project descriptor (usually stored in static final field) as the previous one, or recreated if the descriptor is different (`equals() = false`).

View File

@ -3,33 +3,44 @@ title: Test Project and Testdata Directories
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
The test fixture creates a *test project* environment. Unless you customize the project creation, the test project will have one module with one source root called `src`. The files for the test project exist either in a temporary directory or in an in-memory file system, depending on which implementation of [`TempDirTestFixture`](upsource:///platform/testFramework/src/com/intellij/testFramework/fixtures/TempDirTestFixture.java) is used.
The test fixture creates a *test project* environment.
Unless you customize the project creation, the test project will have one module with one source root called `src`.
The test project files exist either in a temporary directory or in an in-memory file system, depending on which implementation of [`TempDirTestFixture`](upsource:///platform/testFramework/src/com/intellij/testFramework/fixtures/TempDirTestFixture.java) is used.
[`LightPlatformCodeInsightFixtureTestCase`](upsource:///platform/testFramework/src/com/intellij/testFramework/fixtures/LightPlatformCodeInsightFixtureTestCase.java) (renamed to `BasePlatformTestCase` in 2019.2) uses an in-memory implementation; if you set up the test environment by calling `IdeaTestFixtureFactory.createCodeInsightFixture()`, you can specify the implementation to use.
> **WARNING** If your tests use the in-memory implementation, and you abort the execution of your tests, the persisted filesystem caches may get out of sync with the in-memory structures, and you may get spurious errors in your tests.
> If you get an unexpected error after a series of successful runs, **try rerunning the test**, and if that doesn't help, **delete the "system" subdirectory** in your [sandbox directory](/basics/ide_development_instance.md#the-development-instance-sandbox-directory).
In your plugin, you normally store the test data for your tests (such as files on which plugin features will be executed and expected output files) in the `testdata` directory. This is just a directory under the content root of your plugin, but not under a source root. Files in `testdata` usually are not valid source code and must not be compiled.
In your plugin, you usually store the test data for your tests (such as files on which plugin features will be executed and expected output files) in the `testdata` directory.
This is just a directory under your plugin's content root, but not under a source root.
Files in `testdata` usually are not valid source code and must not be compiled.
To specify the location of `testdata`, you must override the `getTestDataPath()` method. The default implementation assumes running as part of the *IntelliJ Platform* source tree and is not appropriate for third-party plugins.
To specify the location of `testdata`, you must override the `getTestDataPath()` method.
The default implementation assumes running as part of the *IntelliJ Platform* source tree and is not appropriate for third-party plugins.
> **NOTE** A very common pattern in *IntelliJ Platform* tests is to use the name of the test method being executed as the base for building the `testdata` file paths. This allows to reuse most of the code between different test methods that test different aspects of the same feature, and this approach is also recommended for third-party plugin tests. The name of the test method can be retrieved using `UsefulTestCase.getTestName()`.
> **NOTE** A very common pattern in *IntelliJ Platform* tests is to use the test method's name being executed as the base for building the `testdata` file paths.
> This allows us to reuse most of the code between different test methods that test various aspects of the same feature, and this approach is also recommended for third-party plugin tests.
> The name of the test method can be retrieved using `UsefulTestCase.getTestName()`.
> **NOTE** If your plugin builds on top of Java support, please see [Tests Prerequisites](/tutorials/writing_tests_for_plugins/tests_prerequisites.md) for setting up your test environment to obtain required _Mock JDK_ automatically.
To copy files or directories from your `testdata` directory to the test project directory, you can use the `copyFileToProject()` and `copyDirectoryToProject()` methods in the [`CodeInsightTestFixture`](upsource:///platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java) class.
Most operations in plugin tests require a file open in the in-memory editor, in which highlighting, completion and other operations will be performed. The in-memory editor instance is returned by `CodeInsightTestFixture.getEditor()`. To copy a file from the `testdata` directory to the test project directory and immediately open it in the editor, you can use the `CodeInsightTestFixture.configureByFile()` or `configureByFiles()` methods. The latter copies multiple files to the test project directory and opens the *first* of them in the in-memory editor.
Most operations in plugin tests require a file open in the in-memory editor, in which highlighting, completion, and other operations will be performed.
The in-memory editor instance is returned by `CodeInsightTestFixture.getEditor()`.
To copy a file from the `testdata` directory to the test project directory and immediately open it in the editor, you can use the `CodeInsightTestFixture.configureByFile()` or `configureByFiles()` methods.
The latter copies multiple files to the test project directory and opens the *first* of them in the in-memory editor.
Alternatively, you can use one of the other methods which take parameters annotated with [`@TestDataFile`](upsource:///platform/testFramework/src/com/intellij/testFramework/TestDataFile.java). These methods copy the specified files from the `testdata` directory to the test project directory, open the first of the specified files in the in-memory editor, and then perform the requested operation such as highlighting or code completion.
Alternatively, you can use one of the other methods which take parameters annotated with [`@TestDataFile`](upsource:///platform/testFramework/src/com/intellij/testFramework/TestDataFile.java).
These methods copy the specified files from the `testdata` directory to the test project directory, open the first of the specified files in the in-memory editor, and then perform the requested operation such as highlighting or code completion.
> **TIP** The IDE supports smart navigation between test code and related test data file(s), see this [blog post](https://blog.jetbrains.com/platform/2017/10/improvements-in-testing-intellij-platform-plugins/) for more details.
> **TIP** The IDE supports smart navigation between test code and related test data file(s); see this [blog post](https://blog.jetbrains.com/platform/2017/10/improvements-in-testing-intellij-platform-plugins/) for more details.
### Special Markup
When a file is opened in the in-memory editor, special markup in the file content can be used to specify the caret position or selection.
When a file is opened in the in-memory editor, special markup in the file content can specify the caret position or selection.
You can use one of the following markers:
* `<caret>` specifies the position where the caret should be placed.
* `<selection>` and `</selection>` specify the start and end of the text range to be selected.
* `<block>` and `</block>` specify the start and end points of the column selection.
* `<selection>` and `</selection>` specify the start and end of the selected text range.
* `<block>` and `</block>` specify the column selection's start and end points.

View File

@ -3,13 +3,19 @@ title: Testing Highlighting
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
A common task when writing plugin tests is testing various kinds of highlighting (inspections, annotators, parser error highlighting, etc.). The *IntelliJ Platform* provides a dedicated utility and markup format for this task.
When writing plugin tests, a common task is testing various kinds of highlighting (inspections, annotators, parser error highlighting, etc.).
The *IntelliJ Platform* provides a dedicated utility and markup format for this task.
To test the highlighting for the file currently loaded into the in-memory editor, you invoke the `checkHighlighting()` method. The parameters to the method specify which severities should be taken into account when comparing the results with the expected results: errors are always taken into account, whereas warnings, weak warnings and infos are optional. Alternatively, you can use the `testHighlighting()` method, which loads a `testdata` file into the in-memory editor and highlights it as a single operation.
To test the highlighting for the file currently loaded into the in-memory editor, you invoke the `checkHighlighting()` method.
The parameters to the method specify which severities should be taken into account when comparing the results with the expected results: errors are always taken into account, whereas warnings, weak warnings, and infos are optional.
Alternatively, you can use the `testHighlighting()` method, which loads a `testdata` file into the in-memory editor and highlights it as a single operation.
If you need to test inspections (rather than generic highlighting provided by a highlighting lexer or annotator), you need to enable inspections that you're testing. This is done by calling `CodeInsightTestFixture.enableInspections()` in the setup method of your test or directly in a test method, before the call to `checkHighlighting()`.
If you need to test inspections (rather than generic highlighting provided by a highlighting lexer or annotator), you need to enable inspections that you're testing.
This is done by calling `CodeInsightTestFixture.enableInspections()` in the setup method of your test or directly in a test method, before the call to `checkHighlighting()`.
The expected results of the highlighting are specified directly in the source file. The platform supports an extensive XML-like markup language for this. In its simplest form, the markup looks like this:
The expected results of the highlighting are specified directly in the source file.
The platform supports an extensive XML-like markup language for this.
In its simplest form, the markup looks like this:
```xml
<warning descr="expected error message">code to be highlighted</warning>
@ -23,7 +29,8 @@ public int <warning descr="The compareTo() method does not reference 'foo' which
}
```
The tag name specifies the severity of the expected highlighting. The following severities are supported:
The tag name specifies the severity of the expected highlighting.
The following severities are supported:
* `<error>`
* `<warning>`

View File

@ -5,21 +5,27 @@ redirect_from:
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
Most of the tests in the *IntelliJ Platform* codebase are *model level functional tests*. What this means is the following:
Most of the tests in the *IntelliJ Platform* codebase are *model level functional tests*.
What this means is the following:
* The tests run in a headless environment that uses real production implementations for the majority of components, except for a number of UI components.
* The tests run in a headless environment that uses real production implementations for most components, except for many UI components.
* The tests usually test a feature as a whole, rather than individual functions that comprise its implementation.
* The tests do not test the Swing UI and work directly with the underlying model instead.
* Most of the tests take a source file or a set of source files as input data, execute a feature, and then compare the output with expected results. Results can be specified as another set of source files, as special markup in the input file, or directly in the test code.
* Most of the tests take a source file or a set of source files as input data, execute a feature, and then compare the output with expected results.
Results can be specified as another set of source files, special markup in the input file, or directly in the test code.
The biggest benefit of this test approach is that tests are very stable and require very little maintenance once they have been written, no matter how much the underlying implementation is refactored or rewritten.
The most significant benefit of this test approach is that tests are very stable and require very little maintenance once written, no matter how much the underlying implementation is refactored or rewritten.
In a product with 15+ years of lifetime that has gone through a large number of internal refactorings, we find that this benefit greatly outweighs the downsides of slower test execution and more difficult debugging of failures being compared to more isolated unit tests.
In a product with 15+ years of a lifetime that has gone through a large number of internal refactorings, we find that this benefit dramatically outweighs the downsides of slower test execution and more difficult debugging of failures being compared to more isolated unit tests.
Another consequence of our testing approach is what our test framework does not provide:
* We do not provide a recommended approach to mocking. We have a few tests in our codebase that use JMock, but in general, we find it difficult to mock all of the interactions with *IntelliJ Platform* components that your plugin class will need to have, and we recommend working with real components instead.
* We do not provide a general-purpose framework for Swing UI testing. You can try using tools such as [FEST](https://code.google.com/p/fest/) or [Sikuli](https://sikulix.com/) for plugin UI testing, but we don't use either of them and cannot provide any guidelines for their use. Internally, we use manual testing for testing our Swing UIs. Please do not use _platform/testGuiFramework_, it is reserved for internal use.
* We do not provide a recommended approach to mocking.
We have a few tests in our codebase that use JMock. Still, in general, we find it difficult to mock all of the interactions with *IntelliJ Platform* components that your plugin class will need to have. We recommend working with real components instead.
* We do not provide a general-purpose framework for Swing UI testing.
You can try using tools such as [FEST](https://code.google.com/p/fest/) or [Sikuli](https://sikulix.com/) for plugin UI testing, but we don't use either of them and cannot provide any guidelines for their use.
Internally, we use manual testing for testing our Swing UIs.
Please do not use _platform/testGuiFramework_; it is reserved for internal use.
## Topics
* [Tests and Fixtures](tests_and_fixtures.md)

View File

@ -3,7 +3,9 @@ title: Tests and Fixtures
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
The *IntelliJ Platform* testing infrastructure is not tied to any specific test framework. In fact, the IntelliJ IDEA Team uses JUnit, TestNG and Cucumber for testing different parts of the project. However, most of the tests are written using JUnit 3.
The *IntelliJ Platform* testing infrastructure is not tied to any specific test framework.
In fact, the IntelliJ IDEA Team uses JUnit, TestNG, and Cucumber for testing different parts of the project.
However, most of the tests are written using JUnit 3.
When writing your tests, you have the choice between using a standard base class to perform the test set up for you and using a fixture class, which lets you perform the setup manually and does not tie you to a specific test framework.

View File

@ -7,10 +7,12 @@ In most cases, once you have the necessary files copied to the test project and
However, for many common cases, the framework provides helper methods that can make testing easier:
* `type()` simulates the typing of a character or string into the in-memory editor.
* `performEditorAction()` simulates the execution of an action in the context of the in-memory editor.
* `complete()` simulates the invocation of code completion and returns the list of lookup elements displayed in the completion list (or `null` if the completion had no suggestions or one suggestion which was auto-inserted).
* `performEditorAction()` simulates the execution of an action in the in-memory editor context.
* `complete()` simulates code completion invocation and returns the list of lookup elements displayed in the completion list (or `null` if the completion had no suggestions or one suggestion which was auto-inserted).
* `findUsages()` simulates the invocation of 'Find Usages' and returns the found usages.
* `findSingleIntention()` in combination with `launchAction()` simulate the invocation of an intention action or inspection quickfix with the specified name.
* `findSingleIntention()` in combination with `launchAction()` simulate the invocation of an intention action or inspection quick fix with the specified name.
* `renameElementAtCaret()` or `rename()` simulate the execution of a rename refactoring.
To compare the results of executing the action with the expected results, you can use the `checkResultByFile()` method. The file with the expected results can also contain [markup](test_project_and_testdata_directories.md#special-markup) to specify the expected caret position or selected text range. If you're testing an action that modifies multiple files (a project-wide refactoring, for example), you can compare an entire directory under the test project with the expected output using `PlatformTestUtil.assertDirectoriesEqual()`.
To compare the results of executing the action with the expected results, you can use the `checkResultByFile()` method.
The file with the expected results can also contain [markup](test_project_and_testdata_directories.md#special-markup) to specify the expected caret position or selected text range.
Suppose you're testing an action that modifies multiple files (a project-wide refactoring, for example). In that case, you can compare an entire directory under the test project with the expected output using `PlatformTestUtil.assertDirectoriesEqual()`.

View File

@ -3,7 +3,8 @@ title: Main Types of Plugins
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
Products based on the *IntelliJ Platform* can be modified and adjusted for custom purposes by adding plugins. All downloadable plugins are available at the [JetBrains Plugins Repository](https://plugins.jetbrains.com/).
Products based on the *IntelliJ Platform* can be modified and adjusted for custom purposes by adding plugins.
All downloadable plugins are available at the [JetBrains Plugins Repository](https://plugins.jetbrains.com/).
The most common types of plugins include:
@ -42,7 +43,8 @@ Refer to the [Custom Language Support Tutorial](/tutorials/custom_language_suppo
## Framework Integration
Framework integration consists of improved code insight features, which are typical for a given framework, as well as the option to use framework-specific functionality directly from the IDE. Sometimes it also includes language support elements for a custom syntax or DSL.
Framework integration consists of improved code insight features, which are typical for a given framework, as well as the option to use framework-specific functionality directly from the IDE.
Sometimes it also includes language support elements for a custom syntax or DSL.
* Specific code insight
* Direct access to framework-specific functionality
@ -61,4 +63,6 @@ Refer to the [Gerrit integration](https://plugins.jetbrains.com/plugin/7272?pr=i
## User Interface Add-Ons
Plugins in this category apply various changes to the standard user interface of the IDE. Some newly added components are interactive and provide new functionality, while others are limited to visual modifications only. The [Random Background](https://plugins.jetbrains.com/plugin/9692-random-background) plugin may serve as an example.
Plugins in this category apply various changes to the standard user interface of the IDE.
Some newly added components are interactive and provide new functionality, while others are limited to visual modifications only.
The [Random Background](https://plugins.jetbrains.com/plugin/9692-random-background) plugin may serve as an example.

View File

@ -8,63 +8,88 @@ The virtual file system (VFS) is a component of the *IntelliJ Platform* that enc
It serves the following main purposes:
* Providing a universal API for working with files regardless of their actual location (on disk, in an archive, on an HTTP server, etc.)
* Tracking file modifications and providing both old and new versions of the file content when a modification is detected.
* Tracking file modifications and providing both old and new versions of the file content when a change is detected.
* Providing a possibility to associate additional persistent data with a file in the VFS.
To provide the last two features, the VFS manages a _persistent snapshot_ of some of the contents of the user's hard disk. The snapshot stores only those files which have been requested at least once through the VFS API, and is asynchronously updated to match the changes happening on the disk.
To provide the last two features, the VFS manages a _persistent snapshot_ of some of the user's hard disk contents.
The snapshot stores only those files which have been requested at least once through the VFS API, and is asynchronously updated to match the changes happening on the disk.
The snapshot is application level, not project level - so, if some file (for example, a class in the JDK) is referenced by multiple projects, only one copy of its contents will be stored in the VFS.
All VFS access operations go through the snapshot.
If some information is requested through the VFS APIs and is not available in the snapshot, it is loaded from disk and stored into the snapshot. If the information is available in the snapshot, the snapshot data is returned. The contents of files and the lists of files in directories are stored in the snapshot only if that specific information was accessed. Otherwise, only file metadata like name, length, timestamp, attributes are stored.
If some information is requested through the VFS APIs and is not available in the snapshot, it is loaded from disk and stored into the snapshot.
If the information is available in the snapshot, the snapshot data is returned.
The contents of files and the lists of files in directories are stored in the snapshot only if that specific information was accessed.
Otherwise, only file metadata like name, length, timestamp, attributes are stored.
> **NOTE** This means that the state of the file system and the file contents displayed in the IntelliJ Platform UI comes from the snapshot, which may not always match the actual contents of the disk.
> For example, in some cases deleted files can still be visible in the UI for some time before the deletion is picked up by the IntelliJ Platform.
> **NOTE** This means that the state of the file system and the file contents displayed in the IntelliJ Platform UI comes from the snapshot, which may not always match the disk's actual contents.
> For example, in some cases, deleted files can still be visible in the UI for some time before the deletion is picked up by the IntelliJ Platform.
The snapshot is updated from disk during _refresh operations_, which generally happen asynchronously. All write operations made through the VFS are synchronous - i.e., the contents are saved to disk immediately.
The snapshot is updated from disk during _refresh operations_, which generally happen asynchronously.
All write operations made through the VFS are synchronous - i.e., the contents are saved to disk immediately.
A refresh operation synchronizes the state of a part of the VFS with the actual disk contents. Refresh operations are explicitly invoked by the *IntelliJ Platform* or plugin code - i.e., when a file is changed on disk while the IDE is running, the change will not be immediately picked up by the VFS. The VFS will be updated during the next refresh operation, which includes the file in its scope.
A refresh operation synchronizes the state of a part of the VFS with the actual disk contents.
Refresh operations are explicitly invoked by the *IntelliJ Platform* or plugin code - i.e., when a file is changed on disk while the IDE is running, the change will not be immediately picked up by the VFS.
The VFS will be updated during the next refresh operation, which includes the file in its scope.
*IntelliJ Platform* refreshes the entire project contents asynchronously on startup. By default, it performs a refresh operation when the user switches to it from another app. Still, users can turn this off via **Settings \| Appearance & Behavior \| System Settings \| Synchronize external changes \[...]**.
*IntelliJ Platform* refreshes the entire project contents asynchronously on startup.
By default, it performs a refresh operation when the user switches to it from another app.
Still, users can turn this off via **Settings \| Appearance & Behavior \| System Settings \| Synchronize external changes \[...]**.
On Windows, Mac, and Linux, a native file watcher process is started that receives file change notifications from the file system and reports them to the *IntelliJ Platform*. If a file watcher is available, a refresh operation looks only at the files that have been reported as changed by the file watcher. If no file watcher is present, a refresh operation walks through all directories and files in the refresh scope.
On Windows, Mac, and Linux, a native file watcher process is started that receives file change notifications from the file system and reports them to the *IntelliJ Platform*.
If a file watcher is available, a refresh operation looks only at the files that have been reported as changed by the file watcher.
If no file watcher is present, a refresh operation walks through all directories and files in the refresh scope.
Refresh operations are based on file timestamps. If the contents of a file were changed, but its timestamp remained the same, the *IntelliJ Platform* will not pick up the updated contents.
Refresh operations are based on file timestamps.
If a file's contents were changed, but its timestamp remained the same, the *IntelliJ Platform* will not pick up the updated contents.
There is currently no facility for removing files from the snapshot. If a file was loaded there once, it remains there forever unless it was deleted from the disk and a refresh operation was called on one of its parent directories.
There is currently no facility for removing files from the snapshot.
If a file was loaded there once, it remains there forever unless it was deleted from the disk, and a refresh operation was called on one of its parent directories.
The VFS itself does not honor ignored files listed in **Settings \| Editor \| File Types** and folders to ignore and excluded folders listed in **Project Structure \| Modules \| Sources \| Excluded**. If the application code accesses them, the VFS will load and return their contents. In most cases, the ignored files and excluded folders must be skipped from processing by higher-level code.
The VFS itself does not honor ignored files listed in **Settings \| Editor \| File Types** and folders to ignore and excluded folders listed in **Project Structure \| Modules \| Sources \| Excluded**.
If the application code accesses them, the VFS will load and return their contents.
In most cases, the ignored files and excluded folders must be skipped from processing by higher-level code.
During the lifetime of a running instance of an IntelliJ Platform IDE, multiple `VirtualFile` instances may correspond to the same disk file. They are equal, have the same `hashCode` and share, the user data.
During the lifetime of a running instance of an IntelliJ Platform IDE, multiple `VirtualFile` instances may correspond to the same disk file.
They are equal, have the same `hashCode`, and share the user data.
## Synchronous and Asynchronous Refreshes
From the point of view of the caller, refresh operations can be either synchronous or asynchronous. In fact, the refresh operations are executed according to their own threading policy, and the synchronous flag simply means that the calling thread will be blocked until the refresh operation (which will most likely run on a different thread) is completed.
From the point of view of the caller, refresh operations can be either synchronous or asynchronous.
In fact, the refresh operations are executed according to their own threading policy. The synchronous flag simply means that the calling thread will be blocked until the refresh operation (which will most likely run on a different thread) is completed.
Both synchronous and asynchronous refreshes can be initiated from any thread. If a refresh is initiated from a background thread, the calling thread must not hold a read action, because otherwise, a deadlock would occur. See [IntelliJ Platform Architectural Overview](/basics/architectural_overview/general_threading_rules.md) for more details on the threading model and read/write actions.
Both synchronous and asynchronous refreshes can be initiated from any thread.
If a refresh is initiated from a background thread, the calling thread must not hold a read action, because otherwise, a deadlock would occur.
See [IntelliJ Platform Architectural Overview](/basics/architectural_overview/general_threading_rules.md) for more details on the threading model and read/write actions.
The same threading requirements also apply to functions like [`LocalFileSystem.refreshAndFindFileByPath()`](upsource:///platform/analysis-api/src/com/intellij/openapi/vfs/LocalFileSystem.java), which perform a partial refresh if the file with the specified path is not found in the snapshot.
In nearly all cases, using asynchronous refreshes is strongly preferred. If there is some code that needs to be executed after the refresh is complete, the code should be passed as a `postRunnable` parameter to one of the refresh methods:
In nearly all cases, using asynchronous refreshes is strongly preferred.
If there is some code that needs to be executed after the refresh is complete, the code should be passed as a `postRunnable` parameter to one of the refresh methods:
* [`RefreshQueue.createSession()`](upsource:///platform/analysis-api/src/com/intellij/openapi/vfs/newvfs/RefreshQueue.java)
* [`VirtualFile.refresh()`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java)
Synchronous refreshes can cause deadlocks in some cases, depending on which locks are held by the thread invoking the refresh operation.
In some cases, synchronous refreshes can cause deadlocks, depending on which locks are held by the thread invoking the refresh operation.
## Virtual File System Events
All changes happening in the virtual file system, either as a result of refresh operations or caused by user actions, are reported as _virtual file system events_. VFS events are always fired in the event dispatch thread, and in a write action.
All changes happening in the virtual file system, either due to refresh operations or caused by user actions, are reported as _virtual file system events_.
VFS events are always fired in the event dispatch thread and in a write action.
The most efficient way to listen to VFS events is to implement [`BulkFileListener`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/newvfs/BulkFileListener.java) and to subscribe with it to the [`VirtualFileManager.VFS_CHANGES`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/VirtualFileManager.java) topic.
A non-blocking variant [`AsyncFileListener`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/AsyncFileListener.java) is also available in 2019.2 or later.
See [How do I get notified when VFS changes?](/basics/architectural_overview/virtual_file.md#how-do-i-get-notified-when-vfs-changes) for implementation details.
> **WARNING** VFS listeners are application level and will receive events for changes happening in *all* the projects opened by the user. You may need to filter out events that aren't relevant to your task (e.g., via [`ProjectFileIndex.isInContent()`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java)).
> **WARNING** VFS listeners are application level and will receive events for changes happening in *all* the projects opened by the user.
> You may need to filter out events that aren't relevant to your task (e.g., via [`ProjectFileIndex.isInContent()`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java)).
VFS events are sent both before and after each change, and you can access the old contents of the file in the before event. Note that events caused by a refresh are sent after the changes have already occurred on disk - so when you process the `beforeFileDeletion` event, for example, the file has already been deleted from disk. However, it is still present in the VFS snapshot, and you can access its last contents using the VFS API.
VFS events are sent both before and after each change, and you can access the old contents of the file in the before event.
Note that events caused by a refresh are sent after the changes have already occurred on disk. So when you process the `beforeFileDeletion` event, for example, the file has already been deleted from disk.
However, it is still present in the VFS snapshot, and you can access its last contents using the VFS API.
Note that a refresh operation fires events only for changes in files that have been loaded in the snapshot. For example, if you accessed a `VirtualFile` for a directory but never loaded its contents using [`VirtualFile.getChildren()`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java), you may not get `fileCreated` notifications when files are created in that directory.
Note that a refresh operation fires events only for changes in files that have been loaded in the snapshot.
For example, if you accessed a `VirtualFile` for a directory but never loaded its contents using [`VirtualFile.getChildren()`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java), you may not get `fileCreated` notifications when files are created in that directory.
If you loaded only a single file in a directory using `VirtualFile.findChild()`, you will get notifications for changes to that file, but you may not get created/deleted notifications for other files in the same directory.

View File

@ -1,3 +1,4 @@
## Code of Conduct
This project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct). Please make sure you read it.
This project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct).
Please make sure you read it.

View File

@ -6,8 +6,8 @@
[![Build](https://github.com/JetBrains/intellij-sdk-docs/workflows/Build/badge.svg)][gh:build]
[![Slack](https://img.shields.io/badge/Slack-%23intellij--platform-blue)][jb:slack]
Learn how to build plugins using IntelliJ Platform SDK for the [JetBrains products][jb:products] by experimenting with
our code samples. These samples show you how features work and help you jumpstart your plugins.
Learn how to build plugins using IntelliJ Platform SDK for the [JetBrains products][jb:products] by experimenting with our code samples.
These samples show you how features work and help you jumpstart your plugins.
There is also [IntelliJ Platform Plugin Template][gh:template] project available.
@ -20,14 +20,12 @@ Previous releases are made available via [tags](https://github.com/JetBrains/int
Code Samples depend on the [IntelliJ Platform SDK][docs] and [Gradle][docs:gradle] as a build system.
The main plugin definition file is stored in the `plugin.xml` file, which is created according
to the [Plugin Configuration File documentation][docs:plugin.xml]. It describes definitions of the actions, extensions,
or listeners provided by the plugin.
The main plugin definition file is stored in the `plugin.xml` file, which is created according to the [Plugin Configuration File documentation][docs:plugin.xml].
It describes definitions of the actions, extensions, or listeners provided by the plugin.
## Code Samples
In the following table, you may find all available samples provided in the separated directories as stand-alone
projects available for running with the Gradle `:runIde` task.
In the following table, you may find all available samples provided in the separated directories as stand-alone projects available for running with the Gradle `:runIde` task.
| Code Sample | Description |
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |

View File

@ -24,4 +24,3 @@ includeBuild '../settings'
includeBuild '../simple_language_plugin'
includeBuild '../tool_window'
includeBuild '../tree_structure_provider'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'comparing_references_inspection'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'conditional_operator_intention'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'editor'

View File

@ -28,4 +28,3 @@ patchPluginXml {
sinceBuild = '202'
untilBuild = '202.*'
}

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'facet'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'framework'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'inspection'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'kotlin'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'live_templates'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'maxOpenProjects'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'module'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'pycharm'

View File

@ -3,7 +3,8 @@
## Quickstart
Project Model Sample project provides five actions that present data extracted using `ProjectRootManager` instance in the message dialogs. Within the implemented actions, you will be able to:
Project Model Sample project provides five actions that present data extracted using `ProjectRootManager` instance in the message dialogs.
Within the implemented actions, you will be able to:
- fetch libraries used in the project,
- retrieve the information about the module details,
- rename the used SDK,

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'project_model'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'project_view_pane'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'projectWizard'

View File

@ -34,4 +34,3 @@ public class DemoSettingsEditor extends SettingsEditor<DemoRunConfiguration> {
myScriptName.setComponent(new TextFieldWithBrowseButton());
}
}

View File

@ -1,2 +1 @@
rootProject.name = 'settings'

View File

@ -1,4 +1,3 @@
// Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
rootProject.name = 'simple_language_plugin'

View File

@ -3,19 +3,27 @@ title: About This Guide
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
This guide is split into several parts, similar to a textbook. Each one builds on the content of the previous section, but it is not necessary to read the guide in order. The [Key Topics](key_topics.md) page aims to link to the pages that are necessary to be able to understand the architecture and get started building plugins.
This guide is split into several parts, similar to a textbook.
Each one builds on the content of the previous section, but it is not necessary to read the guide in order.
The [Key Topics](key_topics.md) page aims to link to the pages that are necessary to be able to understand the architecture and get started building plugins.
> **NOTE** While browsing this guide, you will notice that there are topics that are greyed out. Unfortunately, the guide is not complete and contains placeholders for specific topics. We are working on increasing the coverage, but if you get stuck due to missing content, please see the [Getting Help](getting_help.md) section for details on how to get moving again.
> **NOTE** While browsing this guide, you will notice that there are topics that are greyed out.
> Unfortunately, the guide is not complete and contains placeholders for specific topics.
> We are working on increasing the coverage, but if you get stuck due to missing content, please see the [Getting Help](getting_help.md) section for details on how to get moving again.
>
> The guide is also [Open Source on GitHub](https://github.com/JetBrains/intellij-sdk-docs), and Pull Requests for new content or updates are always gratefully received. A Pull Request does not need to be fully comprehensive - if a little update would help you, it will help other developers too! All pull requests will be reviewed before being accepted, so don't worry about inaccuracies. Please see the [Contributing](/CONTRIBUTING.md) page for details on building the guide locally and contributing.
> The guide is also [Open Source on GitHub](https://github.com/JetBrains/intellij-sdk-docs), and Pull Requests for new content or updates are always gratefully received.
> A Pull Request does not need to be fully comprehensive - if a little update would help you, it will help other developers too! All pull requests will be reviewed before being accepted, so don't worry about inaccuracies.
> Please see the [Contributing](/CONTRIBUTING.md) page for details on building the guide locally and contributing.
#### [Part I - Plugins](/basics/basics.md)
Describes how to create a plugin that can extend the _IntelliJ Platform_. Includes details on how to set up the project, register extension points, target specific versions of the _IntelliJ Platform_, and how to package, deploy, and test your plugins.
Describes how to create a plugin that can extend the _IntelliJ Platform_.
Includes details on how to set up the project, register extension points, target specific versions of the _IntelliJ Platform_, and how to package, deploy, and test your plugins.
#### [Part II - Base Platform](/platform/fundamentals.md)
Describes the foundational layer of the architecture, which provides many features and utilities, such as the component model, the user interface, documents and editors, the virtual file system, settings, threading, and background tasks. The Base Platform layer mainly comprises the functionality of the _IntelliJ Platform_ that does not target language features or parsing.
Describes the foundational layer of the architecture, which provides many features and utilities, such as the component model, the user interface, documents and editors, the virtual file system, settings, threading, and background tasks.
The Base Platform layer mainly comprises the functionality of the _IntelliJ Platform_ that does not target language features or parsing.
#### [Part III - Project Model](/basics/project_structure.md)
@ -23,11 +31,14 @@ Documents the Project Model, which represents the files and configuration of the
#### [Part IV - PSI](/basics/architectural_overview/psi.md)
The Program Structure Interface builds the syntactic and semantic models for lots of different file types. This section describes how to work with the PSI, navigating and manipulating the syntax trees, and also looks at the powerful references system, which allows a syntax tree node to reference an item in the semantic model. It also details how PSI creates and uses indexes.
The Program Structure Interface builds the syntactic and semantic models for lots of different file types.
This section describes how to work with the PSI, navigating and manipulating the syntax trees, and also looks at the powerful references system, which allows a syntax tree node to reference an item in the semantic model.
It also details how PSI creates and uses indexes.
#### Part V - Features
Describes how to extend and interact with various features that use the PSI layer, such as code completion, navigation, <kbd>Alt</kbd>+<kbd>Enter</kbd> items, intentions, refactorings, and more. See also the section on Custom Languages below for language-specific features that are only applicable when adding support for a new language.
Describes how to extend and interact with various features that use the PSI layer, such as code completion, navigation, <kbd>Alt</kbd>+<kbd>Enter</kbd> items, intentions, refactorings, and more.
See also the section on Custom Languages below for language-specific features that are only applicable when adding support for a new language.
#### [Part VI - Testing](/basics/testing_plugins/testing_plugins.md)
@ -35,11 +46,14 @@ Describes the available infrastructure for writing automated tests covering the
#### [Part VII - Custom Languages](/reference_guide/custom_language_support.md)
Plugins frequently extend support for existing languages, such as adding inspections to Java files. This section describes how to add support to the _IntelliJ Platform_ for a new language that isn't supported by default, creating parsers, syntactic and semantic models, and all the features that build on top.
Plugins frequently extend support for existing languages, such as adding inspections to Java files.
This section describes how to add support to the _IntelliJ Platform_ for a new language that isn't supported by default, creating parsers, syntactic and semantic models, and all the features that build on top.
#### [Part VIII - Product Specific](/products/dev_alternate_products.md)
A lot of the functionality in the _IntelliJ Platform_ is language and product agnostic. For example, code inspections work the same in Java as they do in Ruby; it is just the syntax trees and semantic information that is different. This section describes product-specific features, such as specific project model differences and how to target them in a plugin.
A lot of the functionality in the _IntelliJ Platform_ is language and product agnostic.
For example, code inspections work the same in Java as they do in Ruby; it is just the syntax trees and semantic information that is different.
This section describes product-specific features, such as specific project model differences and how to target them in a plugin.
#### Part IX - Custom IDEs

View File

@ -5,7 +5,8 @@ title: Getting Help
## Problems with the Guide
If youre having problems with the guide itself, such as missing, incorrect, or confusing content, please [raise an issue on YouTrack](https://youtrack.jetbrains.com/newIssue?project=IJSDK&clearDraft=true&c=). If the problem is easily solved, you can also submit a [Pull Request on GitHub](https://github.com/JetBrains/intellij-sdk-docs).
If youre having problems with the guide itself, such as missing, incorrect, or confusing content, please [raise an issue on YouTrack](https://youtrack.jetbrains.com/newIssue?project=IJSDK&clearDraft=true&c=).
If the problem is easily solved, you can also submit a [Pull Request on GitHub](https://github.com/JetBrains/intellij-sdk-docs).
If you just want to share feedback on the guide, again, [raise an issue](https://youtrack.jetbrains.com/newIssue?project=IJSDK&clearDraft=true&c=), even if its for a discussion, ideas on improvements or suggestions.
@ -15,7 +16,8 @@ If you just want to share feedback on the guide, again, [raise an issue](https:/
For problems related to code, rather than the content of the guide, you have several options:
* [Plugin Development Forum](https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development) - post a message to the support forum. It is regularly updated with answers by JetBrains team members.
* [Plugin Development Forum](https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development) - post a message to the support forum.
It is regularly updated with answers by JetBrains team members.
* [#intellij-platform on JetBrains Platform Slack](https://plugins.jetbrains.com/slack/) - this chat room is a great place to ask questions, with answers coming from both JetBrains team members and members of the community
Of course, all issues will be used to try and improve this guide.

View File

@ -3,42 +3,58 @@ title: What is the IntelliJ Platform?
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
The _IntelliJ Platform_ is not a product in and of itself but provides a platform for building IDEs. It is used to power JetBrains products such as [IntelliJ IDEA](https://www.jetbrains.com/idea/). It is also Open Source and can be used by third parties to build IDEs, such as [Android Studio](https://developer.android.com/studio/index.html) from Google.
The _IntelliJ Platform_ is not a product in and of itself but provides a platform for building IDEs.
It is used to power JetBrains products such as [IntelliJ IDEA](https://www.jetbrains.com/idea/).
It is also Open Source and can be used by third parties to build IDEs, such as [Android Studio](https://developer.android.com/studio/index.html) from Google.
The IntelliJ Platform provides all of the infrastructures that these IDEs need to provide rich language tooling support. It provides a component-driven, cross-platform JVM based application host with a high-level user interface toolkit for creating tool windows, tree views, and lists (supporting fast search) as well as popup menus and dialogs.
The IntelliJ Platform provides all of the infrastructures that these IDEs need to provide rich language tooling support.
It is a component-driven, cross-platform JVM based application host with a high-level user interface toolkit for creating tool windows, tree views, and lists (supporting fast search) as well as popup menus and dialogs.
It also includes an image editor as well as a full-text editor and provides abstract implementations of syntax highlighting, code folding, code completion, and other rich text editing features.
The IntelliJ Platform has a full-text editor with abstract implementations of syntax highlighting, code folding, code completion, and other rich text editing features.
An image editor is also included.
Furthermore, it includes open APIs to build common IDE functionality, such as a project model and a build system. It also provides an infrastructure for a very rich debugging experience, with language-agnostic advanced breakpoint support, call stacks, watch windows, and expression evaluation.
Furthermore, it includes open APIs to build standard IDE functionality, such as a project model and a build system.
It also provides an infrastructure for a rich debugging experience, with language-agnostic advanced breakpoint support, call stacks, watch windows, and expression evaluation.
But the IntelliJ Platform's real power comes from the Program Structure Interface (PSI). It is a set of functionalities used to parse files and build rich syntactic and semantic models of the code, and to build indexes from this data. PSI powers a lot of functionality, from quick, navigating to files, types, and symbols, to the contents of code completion windows and find usages, code inspections, and code rewriting, for quick fixes or refactorings, as well as many other features.
But the IntelliJ Platform's real power comes from the Program Structure Interface (PSI).
It is a set of functionalities used to parse files, build rich syntactic and semantic models of the code, and build indexes from this data.
PSI powers a lot of functionality, from quick navigating to files, types, and symbols, to the contents of code completion windows and find usages, code inspections, and code rewriting, for quick fixes or refactorings, as well as many other features.
The IntelliJ Platform includes parsers and a PSI model for many languages, and its extensible nature means that it is possible to add support for other languages.
## Plugins
Products built on the IntelliJ Platform are extensible applications, with the platform being responsible for the creation of components, and the injection of dependencies into classes. The IntelliJ Platform fully supports plugins, and JetBrains hosts the [JetBrains Plugin Repository](https://plugins.jetbrains.com) that can be used to distribute plugins that support one or more of the products. It is also possible to host your repositories and distribute plugins separately.
Products built on the IntelliJ Platform are extensible applications, with the platform being responsible for creating components and the injection of dependencies into classes.
The IntelliJ Platform fully supports plugins, and JetBrains hosts the [JetBrains Plugin Repository](https://plugins.jetbrains.com) can be used to distribute plugins that support one or more of the products.
It is also possible to host your repositories and distribute plugins separately.
Plugins can extend the platform in lots of ways, from adding a simple menu item to adding support for a complete language, build system, and debugger. A lot of the existing functionality in the IntelliJ Platform is written as plugins that can be included or excluded depending on the needs of the end product. See the [Quick Start Guide](/basics/basics.md) for more details.
Plugins can extend the platform in many ways, from adding a simple menu item to adding support for a complete language, build system, and debugger.
Many of the existing functionality in the IntelliJ Platform is written as plugins that can be included or excluded depending on the needs of the end product.
See the [Quick Start Guide](/basics/basics.md) for more details.
The IntelliJ Platform is a JVM application, written mostly in Java and Kotlin. You should be experienced with these languages, large libraries written in them, their associated tooling, and large open-source projects to write plugins for products based on the IntelliJ Platform. At this time, it's not possible to extend the IntelliJ Platform in non-JVM languages.
The IntelliJ Platform is a JVM application, written mostly in Java and Kotlin.
You should be experienced with these languages, large libraries written in them, their associated tooling, and large open-source projects to write plugins for products based on the IntelliJ Platform.
At this time, it's not possible to extend the IntelliJ Platform in non-JVM languages.
## Open Source
The IntelliJ Platform is Open Source, under the [Apache license](upsource:///LICENSE.txt), and [hosted on GitHub](https://github.com/JetBrains/intellij-community).
The IntelliJ Platform is Open Source, under the [Apache License](upsource:///LICENSE.txt), and [hosted on GitHub](https://github.com/JetBrains/intellij-community).
While this guide refers to the IntelliJ Platform as a separate entity, there is no "IntelliJ Platform" GitHub repository. Instead, the platform is considered to be an almost complete overlap with the IntelliJ IDEA Community Edition, which is a free and Open Source version of IntelliJ IDEA Ultimate (the GitHub repository linked above is the [JetBrains/intellij-community](https://github.com/JetBrains/intellij-community) repository).
While this guide refers to the IntelliJ Platform as a separate entity, there is no "IntelliJ Platform" GitHub repository.
Instead, the platform is considered to be an almost complete overlap with the IntelliJ IDEA Community Edition, which is a free and Open Source version of IntelliJ IDEA Ultimate (the GitHub repository linked above is the [JetBrains/intellij-community](https://github.com/JetBrains/intellij-community) repository).
The version of the IntelliJ Platform is defined by the version of the corresponding release of IntelliJ IDEA Community Edition.
For example, to build a plugin against IntelliJ IDEA (2019.1.1) build #191.6707.61 means specifying the same build number tag to get the correct Intellij Platform files from the `intellij-community` repository.
For example, to build a plugin against IntelliJ IDEA (2019.1.1), build #191.6707.61 means specifying the same build number tag to get the correct Intellij Platform files from the `intellij-community` repository.
See the [build number ranges](/basics/getting_started/build_number_ranges.md) page for more information about build numbers corresponding to version numbering.
Typically, an IDE that is based on the IntelliJ Platform will include the `intellij-community` repository as a Git submodule and provide configuration to describe which plugins from the `intellij-community`, and which custom plugins will make up the product. This is how the IDEA Ultimate team works, and they contribute code to both the custom plugins and the IntelliJ Platform itself.
Typically, an IDE that is based on the IntelliJ Platform will include the `intellij-community` repository as a Git submodule and provide configuration to describe which plugins from the `intellij-community`, and which custom plugins will make up the product.
This is how the IDEA Ultimate team works, and they contribute code to both the custom plugins and the IntelliJ Platform itself.
### IDEs Based on the IntelliJ Platform
The IntelliJ Platform underlies many JetBrains IDEs.
IntelliJ IDEA Ultimate is a superset of the IntelliJ IDEA Community Edition but includes closed source plugins ([see this feature comparison](https://www.jetbrains.com/idea/features/editions_comparison_matrix.html)). Similarly, other products such as WebStorm and DataGrip are based on the IntelliJ IDEA Community Edition, but with a different set of plugins included and excluding other default plugins.
IntelliJ IDEA Ultimate is a superset of the IntelliJ IDEA Community Edition but includes closed source plugins ([see this feature comparison](https://www.jetbrains.com/idea/features/editions_comparison_matrix.html)).
Similarly, other products such as WebStorm and DataGrip are based on the IntelliJ IDEA Community Edition, but with a different set of plugins included and excluding other default plugins.
This allows plugins to target multiple products, as each product will include base functionality and a selection of plugins from the IntelliJ IDEA Community Edition repository.
> **TIP** Qualifying Open Source projects can [apply for free licenses](https://www.jetbrains.com/community/opensource/) of JetBrains products.
@ -61,8 +77,15 @@ The following IDEs are based on the IntelliJ Platform:
* [CUBA Studio](https://www.cuba-platform.com/)
#### Rider
JetBrains [Rider](https://www.jetbrains.com/rider/) uses the IntelliJ Platform differently than other IntelliJ based IDEs. It uses the IntelliJ Platform to provide the user interface for a C# and .NET IDE, with the standard IntelliJ editors, tool windows, debugging experience, and so on. It also integrates into the standard Find Usages and Search Everywhere UI, and makes use of code completion, syntax highlighting, and so on.
JetBrains [Rider](https://www.jetbrains.com/rider/) uses the IntelliJ Platform differently than other IntelliJ based IDEs.
It uses the IntelliJ Platform to provide the user interface for a C# and .NET IDE, with the standard IntelliJ editors, tool windows, debugging experience, etc.
It also integrates into the standard Find Usages and Search Everywhere UI and uses code completion, syntax highlighting, and so on.
However, Rider doesn't create a full PSI (syntactic and semantic) model for C# files. Instead, it reuses [ReSharper](https://www.jetbrains.com/resharper/) to provide language functionality. All of the C# PSI model, all inspections and code rewriting, such as quick fixes and refactorings are run out of the process, in a command- line version of ReSharper. This means that creating a plugin for Rider involves two parts - a plugin that lives in the IntelliJ "front end" to show user interface, and a plugin that lives in the ReSharper "back end" to analyze and work with the C# PSI.
However, Rider doesn't create a full PSI (syntactic and semantic) model for C# files.
Instead, it reuses [ReSharper](https://www.jetbrains.com/resharper/) to provide language functionality.
All of the C# PSI model, inspections, code rewritings, such as quick fixes and refactorings are run out of the process, in a command-line version of ReSharper.
This means that creating a plugin for Rider involves two parts - a plugin that lives in the IntelliJ "front end" to show user interface, and a plugin that lives in the ReSharper "back end" to analyze and work with the C# PSI.
Fortunately, many plugins can simply work with the ReSharper backend. The Rider takes care of displaying the results of inspections and code completion, and many plugins can be written that don't require an IntelliJ UI component. More details can be found in the *Part VIII - Product Specific* section.
Fortunately, many plugins can simply work with the ReSharper backend.
The Rider takes care of displaying the results of inspections and code completion, and many plugins can be written that don't require an IntelliJ UI component.
More details can be found in the *Part VIII - Product Specific* section.

View File

@ -3,23 +3,28 @@ title: Key Topics
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
The _IntelliJ Platform_ is extensive and very capable, and its size and scope can initially be very daunting. This page is intended to list the key topics that a plugin author would be interested in, and provide quick links to the most common extension points.
The _IntelliJ Platform_ is extensive and very capable, and its size and scope can initially be very daunting.
This page is intended to list the key topics that a plugin author would be interested in, and provide quick links to the most common extension points.
## Essential Concepts
- [Creating Your First Plugin](/basics/getting_started.md).
- [Testing plugins](/basics/testing_plugins/testing_plugins.md).
- Component model - the _IntelliJ Platform_ is a component-based application and is responsible for creating components and injecting dependencies. Understanding this is necessary for building plugins.
- Component model - the _IntelliJ Platform_ is a component-based application and is responsible for creating components and injecting dependencies.
Understanding this is necessary for building plugins.
- [Extension points](/basics/plugin_structure/plugin_extensions.md) - how to register components with extension points, and how to find out what extension points are available.
- [Virtual files](/basics/architectural_overview/virtual_file.md) - all file access should go through the Virtual File System, which abstracts and caches the file system. It means you can work with files that are on the local file system, in a zip file or are old versions from version control.
- [Virtual files](/basics/architectural_overview/virtual_file.md) - all file access should go through the Virtual File System, which abstracts and caches the file system.
It means you can work with files that are on the local file system, in a zip file or are old versions from version control.
## Code Model
The _IntelliJ Platform_'s code model is called the PSI - the [Program Structure Interface](/basics/architectural_overview/psi.md). The PSI parses code, builds indexes, and creates a semantic model.
The _IntelliJ Platform_'s code model is called the PSI - the [Program Structure Interface](/basics/architectural_overview/psi.md).
The PSI parses code, builds indexes, and creates a semantic model.
## Common Extension Points
The _IntelliJ Platform_ is extremely exceptionally, and most features and services can be extended. Some of the common extension points are:
The _IntelliJ Platform_ is extremely exceptionally, and most features and services can be extended.
Some of the common extension points are:
* [Actions](/tutorials/action_system.md) - menu and toolbar items
* [Code inspections](/tutorials/code_inspections.md) - code analysis that looks at the syntax trees and semantic models and highlight issues in the editor.

View File

@ -40,7 +40,8 @@ Use the standard intellij-community copyright notice in all sample plugins autho
Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file."
```
> **NOTE** The copyright statement must appear at the top of every source file. Use the [IntelliJ Platform SDK](https://github.com/JetBrains/intellij-sdk-docs/tree/master/.idea/copyright) copyright profile.
> **NOTE** The copyright statement must appear at the top of every source file.
> Use the [IntelliJ Platform SDK](https://github.com/JetBrains/intellij-sdk-docs/tree/master/.idea/copyright) copyright profile.
## Directory Naming Conventions for SDK Plugins
For _basic_ samples, the plugin directory name is derived from the IntelliJ Platform extension points demonstrated.

View File

@ -47,7 +47,8 @@ Typically, this header is empty, although it is required by Jekyll (if omitted,
The YAML header can contain data that is used when generating the site.
For example, the page title can be specified as a simple piece of Markdown - `# Title`, or it can be specified in the YAML, and the page template displays it appropriately:
> **NOTE** The page copyright notice should appear immediately below the YAML header, as shown below. Use the [IntelliJ Platform SDK](https://github.com/JetBrains/intellij-sdk-docs/tree/master/.idea/copyright) copyright profile.
> **NOTE** The page copyright notice should appear immediately below the YAML header, as shown below.
> Use the [IntelliJ Platform SDK](https://github.com/JetBrains/intellij-sdk-docs/tree/master/.idea/copyright) copyright profile.
```yaml
---
@ -154,7 +155,7 @@ The `upsource:///` URI effectively points to the root of the `intellij-community
* `[`\`plugin.xml\``](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)` links to declarative source code files, use `code` style. ([`plugin.xml`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java))
Examples of this file type include: `settings.gradle`, `plugin.xml` or `theme_basics.theme.json`.
* `[`\`AnAction\``](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)` links to source files for code objects like interfaces and classes, use `code` style but without the file extension. [`AnAction`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)
Examples of this file type include Java and Kotlin.
Examples of this file type includeJava and Kotlin.
* Note the use of \`\` characters surrounding the class name in the link.
* When linking to an API in this manner, the FQN isn't necessary in the link.
* No file extension (*.java, *.kt, *.py, etc.) is used by convention.
@ -181,7 +182,8 @@ In-paragraph code fragments and IntelliJ Platform APIs are formatted according t
### Source Code
Source code is represented by using [GitHub Flavoured Markdown](https://help.github.com/articles/github-flavored-markdown/) code fences, which are three backticks.
Syntax highlighting is applied by specifying the language after the first set of ticks:
Syntax highlighting is applied by specifying the language after the first set of ticks:
```csharp
// Some C# code

View File

@ -10,7 +10,7 @@ redirect_from:
[![Twitter Follow](https://img.shields.io/twitter/follow/JBPlatform?style=flat-square)](https://twitter.com/JBPlatform/)
[![Slack](https://img.shields.io/badge/Slack-%23intellij--platform-blue)](https://plugins.jetbrains.com/slack)
Welcome to the _IntelliJ Platform_ SDK - the primary source of documentation for extending the _IntelliJ Platform_ by creating plugins, custom language support or building a custom IDE.
Welcome to the _IntelliJ Platform_ SDK - the primary source of documentation for extending the _IntelliJ Platform_ by creating plugins, custom language support, or building a custom IDE.
## Getting Started
@ -24,17 +24,20 @@ Welcome to the _IntelliJ Platform_ SDK - the primary source of documentation for
## Updates
See [Content Updates](content_updates.md) for the latest changes. Follow [JBPlatform](https://twitter.com/JBPlatform/) on Twitter and visit [JetBrains Platform Blog](https://blog.jetbrains.com/platform/) for the latest announcements.
See [Content Updates](content_updates.md) for the latest changes.
Follow [JBPlatform](https://twitter.com/JBPlatform/) on Twitter and visit [JetBrains Platform Blog](https://blog.jetbrains.com/platform/) for the latest announcements.
Are you upgrading your plugin to the latest platform release? Make sure to check [Incompatible Changes](/reference_guide/api_changes_list.md) as well as [Notable Changes and Features](/reference_guide/api_notable/api_notable.md).
[Dynamic Plugins](/basics/plugin_structure/dynamic_plugins.md) are available in 2020.1. We've also published our roadmap for the IntelliJ Platform for 2020: [Part I](https://blog.jetbrains.com/idea/2019/12/intellij-platform-roadmap-for-2020/) [Part II](https://blog.jetbrains.com/idea/2020/01/intellij-based-ide-features-roadmap-for-2020/)
[Dynamic Plugins](/basics/plugin_structure/dynamic_plugins.md) are available in 2020.1.
We've also published our roadmap for the IntelliJ Platform for 2020: [Part I](https://blog.jetbrains.com/idea/2019/12/intellij-platform-roadmap-for-2020/) [Part II](https://blog.jetbrains.com/idea/2020/01/intellij-based-ide-features-roadmap-for-2020/)
> **NOTE** If your plugin depends on Java functionality and targets 2019.2 or later, please make sure to follow the steps from this [blog post](https://blog.jetbrains.com/platform/2019/06/java-functionality-extracted-as-a-plugin/).
## Open Source
This guide is Open Source and licensed under Apache 2.0. The source (as Markdown) is [hosted on GitHub](https://github.com/JetBrains/intellij-sdk-docs).
Please see [CONTRIBUTING.md](/CONTRIBUTING.md) for details on how to host the docs locally and contribute.
This guide is Open Source and licensed under Apache 2.0.
The source (as Markdown) is [hosted on GitHub](https://github.com/JetBrains/intellij-sdk-docs).
Please see [CONTRIBUTING.md](/CONTRIBUTING.md) for details on hosting the docs locally and contributing.
Please see [Getting Help](getting_help.md) if you encounter bugs in this guide or require help with missing content.

View File

@ -6,7 +6,7 @@ redirect_from:
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
This section describes the low level fundamental building blocks of the _IntelliJ Platform_:
This section describes the low-level fundamental building blocks of the _IntelliJ Platform_:
* The component model - how the application is hosted and composed. Lifetime and dependency management.
* [Disposers](/basics/disposers.md) - managing object lifetimes and resource cleanup

View File

@ -9,7 +9,7 @@ Plugins can be written in Kotlin or Java, or a mix of both, and are created usin
It's also helpful to be familiar with [Java Swing](https://docs.oracle.com/javase/8/javase-clienttechnologies.htm).
Once completed, plugins can be packaged and distributed at [JetBrains Plugin Repository](https://plugins.jetbrains.com).
Android Studio plugins are not Android modules or apps to run in the Android operating system, such as on a smartphone or tablet.
Android Studio plugins are not Android modules or apps to run in the Android operating system, such as smartphones or tablets.
## Configuring IntelliJ Platform Projects for Android Studio Plugin Development
To create a new Android Studio plugin project, follow the tutorial on the [Getting Started with Gradle](/tutorials/build_system/prerequisites.md) page.

View File

@ -37,5 +37,5 @@ Test your plugin with versions of CLion you intend to support.
## Open Source Plugins for CLion
When learning new APIs, it is helpful to have some representative projects for reference:
* [C/C++ Coverage](https://github.com/zero9178/C-Cpp-Coverage-for-CLion)
* [C/C++ Single File Execution](https://github.com/corochann/SingleFileExecutionPlugin)
* [C/C++ Coverage](https://github.com/zero9178/C-Cpp-Coverage-for-CLion)
* [C/C++ Single File Execution](https://github.com/corochann/SingleFileExecutionPlugin)

View File

@ -5,7 +5,8 @@ title: Plugins Targeting IntelliJ Platform-Based IDEs
## Introduction
Plugin projects can target IDEs other than IntelliJ IDEA, as long as the products are based on the [IntelliJ Platform](/intro/intellij_platform.md).
Such plugins are developed much like plugin projects that target IntelliJ IDEA, and can be written in Kotlin or Java, or a mix of both.
Such plugins are developed much like plugin projects that target IntelliJ IDEA.
They can be written in Kotlin or Java, or a mix of both.
Once completed, the plugins can be packaged and distributed at [JetBrains Plugin Repository](https://plugins.jetbrains.com).
Project configuration attributes common to projects targeting products other than IntelliJ IDEA are described here.
@ -22,7 +23,7 @@ To create a new Gradle plugin project, follow the tutorial on the [Getting Start
The tutorial produces a skeleton Gradle project suitable to use as a starting point.
Modifications are needed to the skeleton project's `build.gradle` and `plugin.xml` files, as described below, and on the individual product pages in Part VIII.
The `build.gradle` file is modified to specify the target product, which determines the APIs available during development.
The `build.gradle` file is modified to specify the target product, determining the APIs available during development.
The `plugin.xml` file is modified to declare the plugin's dependency on modules or libraries.
## Configuring Build.Gradle to Target Products other than IntelliJ IDEA
@ -30,9 +31,8 @@ The best practice is to use the `gradle-intellij-plugin` `intellij.type` [attrib
For example, `PY` for PyCharm professional.
Configuration using an `intellij.type` attribute is explained in the [Product-Specific Attribute](#configuring-plugin-projects-using-a-product-specific-attribute) section below.
However, not all products have an `intellij.type` attribute defined by the `gradle-intellij-plugin`.
For example, PhpStorm.
If the target product does not have an `intellij.type` attribute defined, then the best approach is to configure the project by using the [IntelliJ IDEA Attribute](#configuring-buildgradle-using-the-intellij-idea-product-attribute).
However, not all products have an `intellij.type` attribute defined by the `gradle-intellij-plugin`, for example, PhpStorm.
If the target product does not have an `intellij.type` attribute defined, then the best approach is to configure the project using the [IntelliJ IDEA Attribute](#configuring-buildgradle-using-the-intellij-idea-product-attribute).
### Configuring Plugin Projects Using a Product-Specific Attribute
If the `gradle-intellij-plugin` supports a target product directly, there will be an `intellij.type` [attribute](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) defined.
@ -56,7 +56,7 @@ No additional product-specific configuration needs to be set in `build.gradle`:
If the `gradle-intellij-plugin` does not directly support an IntelliJ Platform-based product, the `build.gradle` file can still be configured to target the desired product.
In this case, the `build.gradle` file is configured to use IntelliJ IDEA (Community or Ultimate Edition) as the basis for the available APIs.
This does have the drawback that APIs not specific to the target product might accidentally be included in the plugin project.
However testing the plugin project in the target product helps to find such mistakes.
However, testing the plugin project in the target product helps to find such mistakes.
Additional configuration must be done to match the version of IntelliJ IDEA to the version of the target product.
Understanding the relationship between build numbers is critical when using this approach to project configuration:
@ -81,7 +81,7 @@ The version of the IntelliJ Platform used to build this product version is BRANC
If the product version isn't clear on the _About_ screen, consult the individual product pages in Part VIII.
The [Other IntelliJ IDEA Versions](https://www.jetbrains.com/idea/download/other.html) page is a way to find build numbers for every product version.
Additional ways include hovering over the version number for a product in ToolBox, or examining the _About_ screen for IntelliJ IDEA Community.
Additional ways include hovering over the version number for a product in ToolBox or examining the _About_ screen for IntelliJ IDEA Community.
In this example, IntelliJ IDEA Community Edition (which defines the IntelliJ Platform) for 2019.2.4 is build number `192.7142.36`.
Although the FIX versions are different, this is not uncommon between products, and the builds are still compatible.
The BRANCH and BUILD numbers match, therefore in this PhpStorm example:
@ -110,7 +110,7 @@ This snippet is an example for configuring the Setup and Running DSLs in a `buil
```groovy
intellij {
// Define IntelliJ Platform against which to build the plugin project.
// Define the IntelliJ Platform against which to build the plugin project.
// Use the IntelliJ Platform BRANCH.BUILD version matching "targetIDE" (PhpStorm)
version '192.7142.36' // baseIntelliJPlatformVersion
type 'IU'
@ -131,7 +131,8 @@ As discussed on the [Plugin Dependencies](/basics/getting_started/plugin_compati
When using features (APIs) specific to the target product, a dependency on the target product module must be declared, as shown in the code snippet below.
Otherwise, if only general IntelliJ Platform features (APIs) are used, then a dependency on `com.intellij.modules.platform` must be declared as discussed in [Plugin Compatibility with IntelliJ Platform Products](/basics/getting_started/plugin_compatibility.md).
> **NOTE** In the special case of a plugin project declaring dependencies only on other plugins, it must also declare a dependency on `com.intellij.modules.platform`. Otherwise, the plugin project is considered to be legacy and will only load in IntelliJ IDEA.
> **NOTE** In the particular case of a plugin project declaring dependencies only on other plugins, it must also declare a dependency on `com.intellij.modules.platform`.
> Otherwise, the plugin project is considered to be legacy and will only load in IntelliJ IDEA.
Continuing with the example of developing a plugin for PhpStorm:

View File

@ -17,14 +17,14 @@ Click on an entry in the table's *Attribute* column to go to the documentation a
To see how these attributes appear in a similar `build.gradle` file for PhpStorm, see [Configuring build.gradle using the IntelliJ IDEA Product Attribute](/products/dev_alternate_products.md#configuring-buildgradle-using-the-intellij-idea-product-attribute).
| `gradle-intellij-plugin` Attribute | Attribute Value |
|-----------|-------|
|------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`intellij.type`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | `IU` for IntelliJ IDEA Ultimate. (The Go plugin isn't compatible with IntelliJ IDEA Community Edition.) |
| [`intellij.version`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | Set to the same `IU` BRANCH.BUILD as the GoLand target version, e.g. `193.5233.102` |
| [`intellij.plugins`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | `org.jetbrains.plugins.go:193.5233.102.83` for the Go plugin.<br>See below for Go plugin version information. |
| [`runIde.ideDirectory`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#running-dsl) | Path to locally installed target version of GoLand. For example, on macOS:<br>`/Users/<user name>/Library/Application Support/JetBrains/Toolbox/apps/Goland/ch-0/193.5233.112/GoLand.app/Contents` |
The version of the Go plugin is explicitly declared because it isn't bundled with IntelliJ IDEA Ultimate Edition.
Select a [version](https://plugins.jetbrains.com/plugin/9568-go/versions) of the Go plugin that is compatible with the IntelliJ Idea Ultimate version.
The Go plugin version is explicitly declared because it isn't bundled with IntelliJ IDEA Ultimate Edition.
Select a [version](https://plugins.jetbrains.com/plugin/9568-go/versions) of the Go plugin compatible with the IntelliJ Idea Ultimate version.
The dependency on the Go plugin APIs must be declared in the `plugin.xml` file.
As described in [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality) table, the `<depends>` tags must declare `com.intellij.modules.go`.

View File

@ -1,11 +1,11 @@
---
title: Example PhpStorm Third Party Plugins
title: Example PhpStorm Third-Party Plugins
redirect_from:
- /phpstorm/existing_plugins.html
---
<!-- Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
This page lists some example PhpStorm plugins created by third party developers.
This page lists some example PhpStorm plugins created by third-party developers.
## Symfony
The Symfony plugin is a free plugin for Symfony framework developers.
@ -20,7 +20,8 @@ There are lots of features included into this plugin, such as Symfony-specific c
## Laravel
The Laravel plugin is a free plugin for Laravel developers.
It provides code completion and navigation for various Laravel components: controllers, routes, views, configuration, services, and translations. You can also use Laravel-specific live templates for generating various Laravel entities.
It provides code completion and navigation for various Laravel components: controllers, routes, views, configuration, services, and translations.
You can also use Laravel-specific live templates for generating various Laravel entities.
* [GitHub](https://github.com/Haehnchen/idea-php-laravel-plugin)
* [Laravel Development in PhpStorm](https://www.jetbrains.com/help/phpstorm/laravel.html)
@ -28,7 +29,7 @@ It provides code completion and navigation for various Laravel components: contr
## Laravel Idea
The Laravel Idea plugin is a paid plugin for Laravel developers.
It provides a wide array of code generation and code completion features, and includes hundreds of useful helpers, including configuration and translation keys, gates names completion, blade support, and so on.
It provides a wide array of code generation and code completion features and includes hundreds of useful helpers, including configuration and translation keys, gates names completion, blade support, etc.
* [Documentation](https://laravel-idea.com/docs/3.x/overview)
* [Issue Tracker](https://github.com/laravel-idea/plugin/issues)
@ -36,8 +37,9 @@ It provides a wide array of code generation and code completion features, and in
* [Laravel Development in PhpStorm](https://www.jetbrains.com/help/phpstorm/laravel.html)
## Magicento
Magicento is a paid PhpStorm plugin for Magento developers. Free limited version is available.
Features include: Goto for factories and template paths, autocomplete for factories, xml files and class names, documentation for xml nodes, evaluation of PHP code inside Magento environment, and much more to come!
Magicento is a paid PhpStorm plugin for Magento developers.
A free limited version is available.
Features include: Goto for factories and template paths, autocomplete for factories, XML files and class names, documentation for XML nodes, evaluation of PHP code inside the Magento environment, and much more to come!
* [Official Magicento Web Site](https://magicento.com/)
* [GitHub](https://github.com/enriquepiatti/Magicento)
@ -45,23 +47,25 @@ Features include: Goto for factories and template paths, autocomplete for factor
## YiiStorm
YiiStorm is a plugin for PhpStorm IDE that is adding code navigation enhancements for Yii framework based projects.
Features are: Going from render and renderPartial to the view file. Includes controllers, partials and widgets. Supports all ways of specifying a view: themes, smarty .tpl views and external actions; Going from model name in relations() to the model class; Going from the $this->widget('path.to.widget.Class') call to the widget class; Going from controller actions() to action class.
Features are: Going from render and renderPartial to the view file.
Includes controllers, partials, and widgets.
Supports all ways of specifying a view: themes, smarty .tpl views and external actions; Going from model name in relations() to the model class; Going from the $this->widget('path.to.widget.Class') call to the widget class; Going from controller actions() to action class.
* [GitHub](https://github.com/cmazx/yiistorm)
* [YiiStorm in PhpStorm Plugins Repository](https://plugins.jetbrains.com/plugin/7182-yiistorm)
## Nette
Nette is a family of mature and stand-alone components for PHP they create a framework.
Nette is a family of mature and stand-alone components for PHP that create a framework.
* [Official Nette web site](https://nette.org/en/)
| Name | Description | Website | GH | Plugin |
|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|----------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|----------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|
| Nette framework helpers | Nette framework helpers make application development in Nette easier. The plugin provides code completion and navigation for Nette components, annotations, and DI service methods in PHP code. It also implements PHP type by `PhpTypeProvider`. | [Nette web](https://nette.org/en/) | [intellij-nette](https://github.com/nette-intellij/intellij-nette) | [Nette plugin](https://plugins.jetbrains.com/plugin/7231-nette-framework-helpers) |
| Latte | Nette Latte plugin provides support for Latte language the safest & truly intuitive templates for PHP. The plugin implements custom language. Partially support PHP like in .php files (code completion, inspections, references to classes, methods, properties, etc.). Supports load config from XML files located in the project. It implements Stub indexes and more around custom language. | [Latte web](https://latte.nette.org/en/) | [intellij-latte](https://github.com/nette-intellij/intellij-latte) | [Latte plugin](https://plugins.jetbrains.com/plugin/7457-latte) |
| Latte | Nette Latte plugin supports Latte language the safest & truly intuitive templates for PHP. The plugin implements custom language. Partially support PHP like in .php files (code completion, inspections, references to classes, methods, properties, etc.). Supports load config from XML files located in the project. It implements Stub indexes and more around custom language. | [Latte web](https://latte.nette.org/en/) | [intellij-latte](https://github.com/nette-intellij/intellij-latte) | [Latte plugin](https://plugins.jetbrains.com/plugin/7457-latte) |
| Neon | Nette Neon is commonly used for any structured data, such as settings, language translations, etc. It is very similar to YAML. The plugin implements custom language. Easy implementation for Go to PHP classes and completion for classes. | [Neon web](https://ne-on.org/) | [intellij-neon](https://github.com/nette-intellij/intellij-neon) | [Neon plugin](https://plugins.jetbrains.com/plugin/7060-neon-support) |
| Nette Tester | Nette Tester is a simple and yet very handy PHP code testing tool. The plugin implements "run configurations" and "run line markers". Supports run configurations in a remote interpreter (eg: in Docker or docker-compose) | [Tester web](https://tester.nette.org/en/) | [intellij-nette-tester](https://github.com/nette-intellij/intellij-nette-tester) | [Tester plugin](https://plugins.jetbrains.com/plugin/8226-nette-tester) |
| Nette Tester | Nette Tester is a simple and yet convenient PHP code testing tool. The plugin implements "run configurations" and "run line markers". Supports run configurations in a remote interpreter (eg: in Docker or docker-compose) | [Tester web](https://tester.nette.org/en/) | [intellij-nette-tester](https://github.com/nette-intellij/intellij-nette-tester) | [Tester plugin](https://plugins.jetbrains.com/plugin/8226-nette-tester) |
## PHP Annotations
The PHP Annotations plugin extends PhpStorm to support annotations in PHPDoc blocks.

View File

@ -44,7 +44,7 @@ public interface PhpTypeProvider2 {
/**
* @param element to deduce type for - using only LOCAL info. <b>THIS IS MOST CRUCIAL ASPECT TO FOLLOW</b>
* @return type for element, null if no insight. You can return a custom signature here to be later decoded by method below.
* @return type for element, null if no insight. You can return a custom signature here to be later decoded by the method below.
*/
@Nullable
String getType(PsiElement element);
@ -206,7 +206,7 @@ public class PhpStaticFactoryTypeProvider extends CompletionContributor implemen
}
```
to make completion work registration is required:
To make completion work registration is required:
```xml
<completion.contributor language="PHP" implementationClass="com.jetbrains.php.lang.psi.resolve.types.PhpStaticFactoryTypeProvider"/>

View File

@ -7,8 +7,8 @@ title: Breaking Changes
PhpStorm 2020.2 introduced support for [PHP union types](https://wiki.php.net/rfc/union_types_v2), which resulted in some PSI-breaking changes.
In earlier versions, type hints in parameters, properties, and return types were parsed inconsistently:
* Return types used a separate `PhpReturnType` wrapper element, which contained the nullability question mark and the class reference of the actual type.
* Parameters and properties used no wrapper element: class references together with nullability question mark were plain children of `Parameter` or `CLASS_FIELDS`.
* Return types used a separate `PhpReturnType` wrapper element, which contained the nullability question mark and the actual type's class reference.
* Parameters and properties used no wrapper element: class references and nullability question mark were plain children of `Parameter` or `CLASS_FIELDS`.
As of PhpStorm 2020.2, class references with the question mark are uniformly wrapped into the `PhpTypeDeclaration` element, which is the parent for `PhpReturnType`, `PhpFieldType`, and `PhpParameterType`.
@ -35,7 +35,8 @@ After 2020.2:
```
## Deprecated `PhpReturnType.getClassReference()`
As of PhpStorm 2020.2, `PhpReturnType.getClassReference()` is deprecated, since there can be multiple class references. This method also became nullable, since in earlier versions an incomplete `?` type was parsed just as a question mark, but now it is parsed as `PhpTypeDeclaration` with empty `getClassReferences()`.
As of PhpStorm 2020.2, `PhpReturnType.getClassReference()` is deprecated, since there can be multiple class references.
This method also became nullable, since in earlier versions an incomplete `?` type was parsed just as a question mark, but now it is parsed as `PhpTypeDeclaration` with empty `getClassReferences()`.
Before 2020.2:

View File

@ -39,7 +39,7 @@ To see how these attributes appear in the `build.gradle` file for PhpStorm, see
| [`intellij.plugins`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | `com.jetbrains.php:193.5233.102` for the PHP plugin.<br>See below for PHP plugin version information. |
| [`runIde.ideDirectory`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#running-dsl) | Path to locally installed target version of PhpStorm. For example, on macOS:<br>`/Users/<user name>/Library/Application Support/JetBrains/Toolbox/apps/PhpStorm/ch-0/193.5233.101/PhpStorm.app/Contents` |
The version of the PHP plugin is explicitly declared because it isn't bundled with IntelliJ IDEA Ultimate Edition.
Select a [version](https://plugins.jetbrains.com/plugin/6610-php/versions) of the PHP plugin that is compatible with the `intellij.version`.
The PHP plugin version is explicitly declared because it isn't bundled with IntelliJ IDEA Ultimate Edition.
Select a [version](https://plugins.jetbrains.com/plugin/6610-php/versions) of the PHP plugin compatible with the `intellij.version`.
The dependency on the PHP plugin APIs must be declared in the `plugin.xml` file, as shown in the tutorial [Configuring plugin.xml](/products/dev_alternate_products.md#configuring-pluginxml) section.

View File

@ -35,7 +35,7 @@ These plugins include the modules `openapi` and `python-psi-api`.
These are considered stable APIs, but care should be taken to test your plugin with any version of PyCharm you wish to support.
## Additional Articles and Resources
* [Webinar Recording: “Live Development of a PyCharm Plugin” with Joachim Ansorg](https://blog.jetbrains.com/pycharm/2019/01/webinar-recording-live-development-of-a-pycharm-plugin-with-joachim-ansorg/)
* [Webinar Recording: "Live Development of a PyCharm Plugin" with Joachim Ansorg](https://blog.jetbrains.com/pycharm/2019/01/webinar-recording-live-development-of-a-pycharm-plugin-with-joachim-ansorg/)
## Open Source Plugins for PyCharm
When learning new development configurations, it is helpful to have some representative projects for reference:

View File

@ -22,7 +22,7 @@ More background information is available in the [Building a .NET IDE with JetBra
The article is a good counterpoint to the ReSharper DevGuide content, which discusses the protocol at the code level.
## Open Source Rider Plugins
When learning new development configurations it is helpful to have some existing plugins for reference.
When learning new development configurations, it is helpful to have some existing plugins for reference.
This list is intended to provide some representative projects.
* [Unity support for both ReSharper and Rider](https://github.com/JetBrains/resharper-unity)
* [F# support in JetBrains Rider](https://github.com/JetBrains/fsharp-support)

Some files were not shown because too many files have changed in this diff Show More