mirror of
https://github.com/JetBrains/intellij-sdk-code-samples.git
synced 2025-07-28 01:07:49 +08:00
parent
5d32cbcfeb
commit
803a9d3ca8
1
.gitignore
vendored
1
.gitignore
vendored
@ -44,4 +44,3 @@ gradle-app.setting
|
|||||||
|
|
||||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
!gradle-wrapper.jar
|
!gradle-wrapper.jar
|
||||||
|
|
||||||
|
@ -5,5 +5,5 @@ title: Code of Conduct
|
|||||||
|
|
||||||
## 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.
|
||||||
|
@ -10,12 +10,18 @@ For information about contributing to the IntelliJ Platform itself, please visit
|
|||||||
Here are some useful things to know before authoring SDK content and submitting your Pull Request.
|
Here are some useful things to know before authoring SDK content and submitting your Pull Request.
|
||||||
* Dummy list item
|
* Dummy list item
|
||||||
{:toc}
|
{:toc}
|
||||||
|
|
||||||
## Setting Up the Documentation Build Environment
|
## 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
|
### Developing Documentation with Docker
|
||||||
|
|
||||||
@ -31,18 +37,25 @@ Follow these steps to work with Docker:
|
|||||||
* Start the Docker container called `intellij-sdk-docs`.
|
* Start the Docker container called `intellij-sdk-docs`.
|
||||||
* Forward port 4000 from the Docker container to port 4000 on the Docker client.
|
* 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`.
|
|
||||||
|
|
||||||
> **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`).
|
* 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`.
|
||||||
|
|
||||||
* Run the commands in the Dockerfile's `CMD` instruction to execute:
|
> **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`.
|
||||||
* `rake bootstrap`, which ensures all of the prerequisites are installed,
|
> 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,
|
||||||
* `rake preview`, which builds the site and starts to host it.
|
* `rake preview`, which builds the site and starts to host it.
|
||||||
* Finally, you can access the newly created site by visiting [http://localhost:4000/intellij/sdk/docs/](http://localhost:4000/intellij/sdk/docs/), or by using the IP address of the Docker client virtual machine (see the note above).
|
* Finally, you can access the newly created site by visiting [http://localhost:4000/intellij/sdk/docs/](http://localhost:4000/intellij/sdk/docs/), or by using the IP address of the Docker client virtual machine (see the note above).
|
||||||
|
|
||||||
@ -52,11 +65,13 @@ To build the documentation site, you need:
|
|||||||
|
|
||||||
* Ruby 2 - Jekyll is a Ruby application.
|
* 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.
|
* 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
|
||||||
|
|
||||||
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`
|
* `gem install bundler`
|
||||||
|
|
||||||
@ -73,27 +88,30 @@ This installation is easier if you use [Chocolatey](https://chocolatey.org), a p
|
|||||||
* By default, this is `C:\tools\DevKit\config.yml`
|
* By default, this is `C:\tools\DevKit\config.yml`
|
||||||
* Add the line `- C:\tools\ruby21` (including the leading minus sign)
|
* 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
|
### Bootstrapping the Documentation Build Environment
|
||||||
|
|
||||||
1. Ensure Bundler is installed - `gem install bundler`.
|
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`).
|
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.
|
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.
|
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.
|
6. `rake preview` - this will build the site, and host it in a local webserver.
|
||||||
|
|
||||||
### Building and Previewing the Site
|
### 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.
|
> **NOTE** You must use `localhost` as hostname, _NOT_ 0.0.0.0, otherwise fonts fail to load.
|
||||||
|
|
||||||
## Documentation Repository Submodules
|
## Documentation Repository Submodules
|
||||||
The `sdkdocs-template` directory is a Git submodule, and it contains a submodule to the private `webhelp-template` repository.
|
The `sdkdocs-template` directory is a Git submodule, and it contains a submodule to the private `webhelp-template` repository.
|
||||||
The `sdkdocs-template` repository contains build scripts and compiled and minified JS and CSS that allow the site to run.
|
The `sdkdocs-template` repository contains build scripts and compiled and minified JS and CSS that allow the site to run.
|
||||||
The private `webhelp-template` repository contains the code to build the JS and CSS.
|
The private `webhelp-template` repository contains the code to build the JS and CSS.
|
||||||
It is currently closed source, but the plan is to make it open-source at some point, in which case it is likely the two repositories will be merged.
|
It is currently closed source, but the plan is to make it open-source at some point, in which case it is likely the two repositories will be merged.
|
||||||
|
|
||||||
After cloning, a submodule needs to be initialized and updated:
|
After cloning, a submodule needs to be initialized and updated:
|
||||||
@ -103,14 +121,14 @@ git submodule init
|
|||||||
git submodule update
|
git submodule update
|
||||||
```
|
```
|
||||||
|
|
||||||
Initialization creates a `.gitmodules` file, register a submodule in the `sdkdocs-template` folder and check out the files.
|
Initialization creates a `.gitmodules` file, register a submodule in the `sdkdocs-template` folder and check out the files.
|
||||||
Note that when a repository is added as a submodule, it doesn't get a `.git` folder, but instead gets a `.git` file that points to the actual location of the `.git` folder.
|
Note that when a repository is added as a submodule, it doesn't get a `.git` folder, but instead gets a `.git` file that points to the actual location of the `.git` folder.
|
||||||
|
|
||||||
A submodule can be updated using standard git commands such as `git pull`.
|
A submodule can be updated using standard git commands such as `git pull`.
|
||||||
It can be switched to a different branch using `git checkout`, and any changes to the currently checked out revision need to be committed back into the main repository using git commands.
|
It can be switched to a different branch using `git checkout`, and any changes to the currently checked out revision need to be committed back into the main repository using git commands.
|
||||||
A submodule is initially cloned at a specific revision, and not as part of a branch.update
|
A submodule is initially cloned at a specific revision, and not as part of a branch.update
|
||||||
|
|
||||||
If changes are made to the submodule, they should be made on a branch to a clone, and a Pull Request sent.
|
If changes are made to the submodule, they should be made on a branch to a clone, and a Pull Request sent.
|
||||||
Changes can be made and committed, and the hosting repository will need to commit a pointer to the current version of the submodule.
|
Changes can be made and committed, and the hosting repository will need to commit a pointer to the current version of the submodule.
|
||||||
|
|
||||||
If there are any problems with the `sdkdocs-template`, please [raise an issue](https://github.com/JetBrains/sdkdocs-template/issues).
|
If there are any problems with the `sdkdocs-template`, please [raise an issue](https://github.com/JetBrains/sdkdocs-template/issues).
|
||||||
@ -119,10 +137,9 @@ If there are any problems with the `sdkdocs-template`, please [raise an issue](h
|
|||||||
Content contributions to the IntelliJ Platform SDK are welcome.
|
Content contributions to the IntelliJ Platform SDK are welcome.
|
||||||
Please download or clone the open-source SDK project from [GitHub](https://github.com/JetBrains/intellij-sdk-docs), make additions or changes, and submit a pull request.
|
Please download or clone the open-source SDK project from [GitHub](https://github.com/JetBrains/intellij-sdk-docs), make additions or changes, and submit a pull request.
|
||||||
Before creating or altering content, please consult these guides:
|
Before creating or altering content, please consult these guides:
|
||||||
* [SDK Documentation Style Guide](intro/sdk_style.md).
|
* [SDK Documentation Style Guide](intro/sdk_style.md).
|
||||||
This guide describes documentation conventions in terms of Markdown syntax.
|
This guide describes documentation conventions in terms of Markdown syntax.
|
||||||
Always test documentation changes using a [preview](#building-and-previewing-the-site) of the site.
|
Always test documentation changes using a [preview](#building-and-previewing-the-site) of the site.
|
||||||
* [SDK Code Sample Guidelines](intro/sdk_code_guidelines.md).
|
* [SDK Code Sample Guidelines](intro/sdk_code_guidelines.md).
|
||||||
Conventions for code sample organization, project settings, and naming conventions are described in this document.
|
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.
|
Always test code changes by building and testing the SDK code sample.
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
Welcome to the repository for [IntelliJ Platform SDK Documentation](https://www.jetbrains.org/intellij/sdk/docs/) site.
|
Welcome to the repository for [IntelliJ Platform SDK Documentation](https://www.jetbrains.org/intellij/sdk/docs/) site.
|
||||||
|
|
||||||
The code samples can also be found in [IntelliJ SDK Code Samples](https://github.com/JetBrains/intellij-sdk-code-samples) mirror repository.
|
The code samples can also be found in [IntelliJ SDK Code Samples](https://github.com/JetBrains/intellij-sdk-code-samples) mirror repository.
|
||||||
|
|
||||||
## Feedback
|
## Feedback
|
||||||
Please report any content inconsistencies, outdated materials, cosmetic issues, and other defects using the channels listed in [Getting Help](https://www.jetbrains.org/intellij/sdk/docs/intro/getting_help.html).
|
Please report any content inconsistencies, outdated materials, cosmetic issues, and other defects using the channels listed in [Getting Help](https://www.jetbrains.org/intellij/sdk/docs/intro/getting_help.html).
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
* [Plugin Configuration File](basics/plugin_structure/plugin_configuration_file.md)
|
* [Plugin Configuration File](basics/plugin_structure/plugin_configuration_file.md)
|
||||||
* [Plugin Logo (Icon)](basics/plugin_structure/plugin_icon_file.md)
|
* [Plugin Logo (Icon)](basics/plugin_structure/plugin_icon_file.md)
|
||||||
* [Plugin Dependencies](basics/plugin_structure/plugin_dependencies.md)
|
* [Plugin Dependencies](basics/plugin_structure/plugin_dependencies.md)
|
||||||
* [Dynamic Plugins](basics/plugin_structure/dynamic_plugins.md)
|
* [Dynamic Plugins](basics/plugin_structure/dynamic_plugins.md)
|
||||||
* [IntelliJ Platform Artifacts Repositories](reference_guide/intellij_artifacts.md)
|
* [IntelliJ Platform Artifacts Repositories](reference_guide/intellij_artifacts.md)
|
||||||
* [Kotlin for Plugin Developers](tutorials/kotlin.md)
|
* [Kotlin for Plugin Developers](tutorials/kotlin.md)
|
||||||
* [Internal Actions Menu](reference_guide/internal_actions/internal_actions_intro.md)
|
* [Internal Actions Menu](reference_guide/internal_actions/internal_actions_intro.md)
|
||||||
|
@ -6,7 +6,7 @@ title: Glossary
|
|||||||
## A
|
## A
|
||||||
|
|
||||||
Abstract Syntax Tree _(AST)_
|
Abstract Syntax Tree _(AST)_
|
||||||
: The [Abstract Syntax Tree](/reference_guide/custom_language_support/implementing_parser_and_psi.md) represents the structure of source input files.
|
: The [Abstract Syntax Tree](/reference_guide/custom_language_support/implementing_parser_and_psi.md) represents the structure of source input files.
|
||||||
→ _Program Structure Interface_
|
→ _Program Structure Interface_
|
||||||
|
|
||||||
Annotator
|
Annotator
|
||||||
@ -49,7 +49,7 @@ Local History _(LVCS)_
|
|||||||
: A builtin → _Version Control System_ tracking all changes in the project [locally](https://www.jetbrains.com/help/idea/local-history.html).
|
: A builtin → _Version Control System_ tracking all changes in the project [locally](https://www.jetbrains.com/help/idea/local-history.html).
|
||||||
|
|
||||||
## J
|
## J
|
||||||
|
|
||||||
JetBrains Project System _(JPS)_
|
JetBrains Project System _(JPS)_
|
||||||
: Represents the project model in [External Build](/reference_guide/frameworks_and_external_apis/external_builder_api.md#accessing-project-model-and-configuration-from-external-build) process.
|
: Represents the project model in [External Build](/reference_guide/frameworks_and_external_apis/external_builder_api.md#accessing-project-model-and-configuration-from-external-build) process.
|
||||||
|
|
||||||
@ -77,13 +77,13 @@ Stubs
|
|||||||
|
|
||||||
## V
|
## V
|
||||||
Version Control System _(VCS)_
|
Version Control System _(VCS)_
|
||||||
: The API for [Version Control System](/reference_guide/vcs_integration_for_plugins.md) allows accessing builtin as well as adding custom implementations.
|
: The API for [Version Control System](/reference_guide/vcs_integration_for_plugins.md) allows accessing builtin as well as adding custom implementations.
|
||||||
|
|
||||||
Virtual File _(VF)_
|
Virtual File _(VF)_
|
||||||
: A [Virtual File](/basics/architectural_overview/virtual_file.md) represents a file in a → _Virtual File System_.
|
: A [Virtual File](/basics/architectural_overview/virtual_file.md) represents a file in a → _Virtual File System_.
|
||||||
|
|
||||||
Virtual File System _(VFS)_
|
Virtual File System _(VFS)_
|
||||||
: A [Virtual File System](/basics/virtual_file_system.md) provides a unified API for working with files represented as → _Virtual File_.
|
: A [Virtual File System](/basics/virtual_file_system.md) provides a unified API for working with files represented as → _Virtual File_.
|
||||||
|
|
||||||
|
|
||||||
## W
|
## W
|
||||||
|
@ -15,10 +15,9 @@ 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. -->
|
<!-- 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,
|
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).
|
||||||
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.
|
||||||
> **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.
|
|
||||||
|
|
||||||
For your convenience pages previously part of this documentation are linked below:
|
For your convenience pages previously part of this documentation are linked below:
|
||||||
|
|
||||||
@ -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 Developers List](https://plugins.jetbrains.com/docs/marketplace/plugin-developers-list.html)
|
||||||
* [Plugin Recommendations](https://plugins.jetbrains.com/docs/marketplace/intellij-plugin-recommendations.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)
|
* [Custom Release Channels](https://plugins.jetbrains.com/docs/marketplace/custom-release-channels.html)
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@ The following independent companies and individuals provide paid plugin consulti
|
|||||||
| Joachim Ansorg | [www.plugin-dev.com](https://www.plugin-dev.com) | -/- |
|
| Joachim Ansorg | [www.plugin-dev.com](https://www.plugin-dev.com) | -/- |
|
||||||
| Daniel Espendiller | <a href="mailto:daniel@espendiller.net">daniel@espendiller.net</a> | -/- |
|
| Daniel Espendiller | <a href="mailto:daniel@espendiller.net">daniel@espendiller.net</a> | -/- |
|
||||||
| Robert Ekendahl | [www.edaphic.studio](https://www.edaphic.studio) | Custom Language support |
|
| Robert Ekendahl | [www.edaphic.studio](https://www.edaphic.studio) | Custom Language support |
|
||||||
| Patrick Scheibe | [www.halirutan.de](https://halirutan.de/) | Plugins: [Wolfram Language](https://plugins.jetbrains.com/plugin/7232-wolfram-language), [Key Promoter X](https://plugins.jetbrains.com/plugin/9792-key-promoter-x). Highly active in the [#intellij-platform on JetBrains Platform Slack](https://plugins.jetbrains.com/slack/).
|
| Patrick Scheibe | [www.halirutan.de](https://halirutan.de/) | Plugins: [Wolfram Language](https://plugins.jetbrains.com/plugin/7232-wolfram-language), [Key Promoter X](https://plugins.jetbrains.com/plugin/9792-key-promoter-x). Highly active in the [#intellij-platform on JetBrains Platform Slack](https://plugins.jetbrains.com/slack/).
|
||||||
| Alexander Schwartz | [msg.group](https://msg.group/), <a href="mailto:alexander.schwartz@msg.group">alexander.schwartz@msg.group</a> | Custom Language support around documentation-as-code, especially AsciiDoc and Antora. Plugin: [AsciiDoc](https://plugins.jetbrains.com/plugin/7391-asciidoc)
|
| Alexander Schwartz | [msg.group](https://msg.group/), <a href="mailto:alexander.schwartz@msg.group">alexander.schwartz@msg.group</a> | Custom Language support around documentation-as-code, especially AsciiDoc and Antora. Plugin: [AsciiDoc](https://plugins.jetbrains.com/plugin/7391-asciidoc)
|
||||||
| Alexey Stukalov | <a href="mailto:info@cuba-platform.com">info@cuba-platform.com</a>, [www.haulmont.com](https://www.haulmont.com/services/cuba-platform-services/support/) | Plugins: [CUBA](https://plugins.jetbrains.com/plugin/7249-cuba).
|
| Alexey Stukalov | <a href="mailto:info@cuba-platform.com">info@cuba-platform.com</a>, [www.haulmont.com](https://www.haulmont.com/services/cuba-platform-services/support/) | Plugins: [CUBA](https://plugins.jetbrains.com/plugin/7249-cuba).
|
||||||
| Edument | <a href="mailto:jonathan@edument.cz">jonathan@edument.cz</a>, [edument.se](https://www.edument.se/en/page/intellij-platform-development) | Developers of [Comma IDE](https://commaide.com/) |
|
| Edument | <a href="mailto:jonathan@edument.cz">jonathan@edument.cz</a>, [edument.se](https://www.edument.se/en/page/intellij-platform-development) | Developers of [Comma IDE](https://commaide.com/) |
|
||||||
|
|
||||||
Please [submit a PR or file a YouTrack issue](/intro/getting_help.md) for changes or additions to this list.
|
Please [submit a PR or file a YouTrack issue](/intro/getting_help.md) for changes or additions to this list.
|
||||||
|
@ -24,7 +24,7 @@ The following links represent useful resources for working with the _IntelliJ Pl
|
|||||||
* [PsiViewer](https://plugins.jetbrains.com/plugin/227-psiviewer)
|
* [PsiViewer](https://plugins.jetbrains.com/plugin/227-psiviewer)
|
||||||
* [Grammar-Kit](https://github.com/JetBrains/Grammar-Kit) & [Grammar-Kit Folder](https://plugins.jetbrains.com/plugin/12983-grammar-kit-folder)
|
* [Grammar-Kit](https://github.com/JetBrains/Grammar-Kit) & [Grammar-Kit Folder](https://plugins.jetbrains.com/plugin/12983-grammar-kit-folder)
|
||||||
* [Indices Viewer](https://plugins.jetbrains.com/plugin/13029-indices-viewer/)
|
* [Indices Viewer](https://plugins.jetbrains.com/plugin/13029-indices-viewer/)
|
||||||
|
|
||||||
### Webinars
|
### Webinars
|
||||||
* [How We Built Comma, the Raku IDE, on the IntelliJ Platform](https://blog.jetbrains.com/platform/2020/01/webinar-recording-how-we-built-comma-the-raku-ide-on-the-intellij-platform/) Jonathan Worthington, 2020
|
* [How We Built Comma, the Raku IDE, on the IntelliJ Platform](https://blog.jetbrains.com/platform/2020/01/webinar-recording-how-we-built-comma-the-raku-ide-on-the-intellij-platform/) Jonathan Worthington, 2020
|
||||||
* [Building IntelliJ IDEA plugins in Scala](https://www.youtube.com/watch?v=IPO-cY_giNA) Igal Tabachnik, 2020
|
* [Building IntelliJ IDEA plugins in Scala](https://www.youtube.com/watch?v=IPO-cY_giNA) Igal Tabachnik, 2020
|
||||||
|
@ -4,11 +4,11 @@ title: Action System
|
|||||||
<!-- 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. -->
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
The actions system is an extension point that allows plugins to add their items to IntelliJ Platform-based IDE menus and toolbars.
|
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.
|
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.
|
The action implementation determines the contexts in which an action is available, and its functionality when selected in the UI.
|
||||||
Registration determines where an action appears in the IDE UI.
|
Registration determines where an action appears in the IDE UI.
|
||||||
Once implemented and registered, an action receives callbacks from the IntelliJ Platform in response to user gestures.
|
Once implemented and registered, an action receives callbacks from the IntelliJ Platform in response to user gestures.
|
||||||
|
|
||||||
@ -21,43 +21,43 @@ The rest of this page is an overview of actions as an extension point.
|
|||||||
|
|
||||||
## Action Implementation
|
## Action Implementation
|
||||||
An action is a class derived from the abstract class [`AnAction`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java).
|
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.
|
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
|
> **WARNING** Classes based on `AnAction` do not have class fields of any kind.
|
||||||
exists for the entire lifetime of the application. If `AnAction` class uses a field to store data that has a shorter
|
> This is because an instance of `AnAction` class exists for the entire lifetime of the application.
|
||||||
lifetime and doesn't clear this data promptly, the data leaks. For example, any `AnAction` data that exists
|
> 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.
|
||||||
only within the context of a `Project` causes the `Project` to be kept in memory after the user has closed it.
|
> 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
|
### Principal Implementation Overrides
|
||||||
Every IntelliJ Platform action should override `AnAction.update()` and must override `AnAction.actionPerformed()`.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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 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, which is demonstrated in the [Grouping Actions](/tutorials/action_system/grouping_action.md#adding-child-actions-to-the-dynamic-group) tutorial.
|
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.
|
However, the `update()` and `actionPerformed()` methods are essential to basic operation.
|
||||||
|
|
||||||
### Overriding the AnAction.update Method
|
### Overriding the AnAction.update Method
|
||||||
The method `AnAction.update()` is periodically called by the IntelliJ Platform in response to user gestures.
|
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.
|
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.
|
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.
|
For example, checking selection in a tree or a list is considered valid, but working with the file system is not.
|
||||||
|
|
||||||
> **TIP** If the new state of an action cannot be determined quickly, then evaluation should be performed in the `AnAction.actionPerformed()` method, and notify the user that the action cannot be executed if the context isn't suitable.
|
> **TIP** If the new state of an action cannot be determined quickly, then evaluation should be performed in the `AnAction.actionPerformed()` method, and notify the user that the action cannot be executed if the context isn't suitable.
|
||||||
|
|
||||||
#### Determining the Action Context
|
#### Determining the Action Context
|
||||||
The `AnActionEvent` object passed to `update()` carries information about the current context for the action.
|
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()`.
|
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.
|
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()`.
|
Accessing this information is relatively light-weight and is suited for `AnAction.update()`.
|
||||||
|
|
||||||
@ -66,8 +66,8 @@ Based on information about the action context, the `AnAction.update()` method ca
|
|||||||
An action's enable/disable state and visibility are set using methods of the `Presentation` object, which is accessed using `AnActionEvent.getPresentation()`.
|
An action's enable/disable state and visibility are set using methods of the `Presentation` object, which is accessed using `AnActionEvent.getPresentation()`.
|
||||||
|
|
||||||
The default `Presentation` object is a set of descriptive information about a menu or toolbar action.
|
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.
|
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).
|
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.
|
However, some can be changed at runtime using the methods of the `Presentation` object associated with an action.
|
||||||
|
|
||||||
@ -79,47 +79,48 @@ A toolbar action displays its enabled (or selected) icon, depending on the user
|
|||||||
|
|
||||||
When an action is disabled `AnAction.actionPerformed()` will not be called.
|
When an action is disabled `AnAction.actionPerformed()` will not be called.
|
||||||
Toolbar actions display their respective icons for the disabled state.
|
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.
|
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.
|
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.
|
> **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.
|
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.
|
||||||
|
|
||||||
An example of enabling a menu action based on whether a project is open is demonstrated in [`PopupDialogAction.update()`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/action_basics/src/main/java/org/intellij/sdk/action/PopupDialogAction.java) method.
|
An example of enabling a menu action based on whether a project is open is demonstrated in [`PopupDialogAction.update()`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/action_basics/src/main/java/org/intellij/sdk/action/PopupDialogAction.java) method.
|
||||||
|
|
||||||
### Overriding the AnAction.actionPerformed Method
|
### Overriding the AnAction.actionPerformed Method
|
||||||
When the user selects an enabled action, be it from a menu or toolbar, the action's `AnAction.actionPerformed()` method is called.
|
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.
|
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.
|
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.
|
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.
|
||||||
|
|
||||||
<!-- TODO: does this all happen inside a transaction? Does that ensure the undo step? -->
|
<!-- TODO: does this all happen inside a transaction? Does that ensure the undo step? -->
|
||||||
|
|
||||||
An example of inspecting PSI elements is demonstrated in the SDK code sample `action_basics` [`PopupDialogAction.actionPerformed()`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/action_basics/src/main/java/org/intellij/sdk/action/PopupDialogAction.java) method.
|
An example of inspecting PSI elements is demonstrated in the SDK code sample `action_basics` [`PopupDialogAction.actionPerformed()`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/action_basics/src/main/java/org/intellij/sdk/action/PopupDialogAction.java) method.
|
||||||
|
|
||||||
### Action IDs
|
### Action IDs
|
||||||
Every action and action group has a unique identifier.
|
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.
|
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).
|
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
|
### Grouping Actions
|
||||||
Groups organize actions into logical UI structures, which in turn can contain other groups.
|
Groups organize actions into logical UI structures, which in turn can contain other groups.
|
||||||
A group of actions can form a toolbar or a menu.
|
A group of actions can form a toolbar or a menu.
|
||||||
Subgroups of a group can form submenus of 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.
|
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.
|
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 -->
|
<!-- TODO: Reconcile ActionPlaces vs. PlatformActions -->
|
||||||
|
|
||||||
#### Presentation
|
#### Presentation
|
||||||
For every place where the action appears, a new [`Presentation`](upsource:///platform/platform-api/src/com/intellij/ide/presentation/Presentation.java) is created.
|
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.
|
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.
|
Different presentations for the action are created by copying the Presentation returned by the `AnAction.getTemplatePresentation()` method.
|
||||||
|
|
||||||
#### Compact Attribute
|
#### 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.
|
See the [Grouping Actions](/tutorials/action_system/grouping_action.md) tutorial for examples of creating action groups.
|
||||||
|
|
||||||
## Registering Actions
|
## 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
|
||||||
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
|
#### 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.
|
> **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."
|
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.
|
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 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.
|
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.
|
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.
|
||||||
|
|
||||||
@ -168,33 +169,33 @@ An example of using `<override-text>` is demonstrated in the [Creating Actions](
|
|||||||
Action and group localization use resource bundles containing property files, each file consisting of `key=value` pairs.
|
Action and group localization use resource bundles containing property files, each file consisting of `key=value` pairs.
|
||||||
The [`action_basics`](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/action_basics) plugin demonstrates using a resource bundle to localize the group and action entries added to the Editor Popup Menu.
|
The [`action_basics`](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/action_basics) plugin demonstrates using a resource bundle to localize the group and action entries added to the Editor Popup Menu.
|
||||||
|
|
||||||
When localizing actions and groups, the `text=""` and `description=""` attributes are not declared in `plugin.xml`.
|
When localizing actions and groups, the `text=""` and `description=""` attributes are not declared in `plugin.xml`.
|
||||||
Instead, those attribute values vary depending on the locale and get declared in a resource bundle.
|
Instead, those attribute values vary depending on the locale and get declared in a resource bundle.
|
||||||
|
|
||||||
The name and location of the resource bundle must be declared in the `plugin.xml` file.
|
The name and location of the resource bundle must be declared in the `plugin.xml` file.
|
||||||
In the case of `action_basics`, only a default localization resource bundle is provided:
|
In the case of `action_basics`, only a default localization resource bundle is provided:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<resource-bundle>messages.BasicActionsBundle</resource-bundle>
|
<resource-bundle>messages.BasicActionsBundle</resource-bundle>
|
||||||
```
|
```
|
||||||
|
|
||||||
For Actions, the `key` in property files incorporates the action `id` in this specific structure:
|
For Actions, the `key` in property files incorporates the action `id` in this specific structure:
|
||||||
* `action.<action-id>.text=Translated Action Text`
|
* `action.<action-id>.text=Translated Action Text`
|
||||||
* `action.<action-id>.description=Translated Action Description`
|
* `action.<action-id>.description=Translated Action Description`
|
||||||
|
|
||||||
If `<override-text>` is used for an action `id`, the `key` includes the `<place>` attribute:
|
If `<override-text>` is used for an action `id`, the `key` includes the `<place>` attribute:
|
||||||
* `action.<action-id>.<place>.text=Place-dependent Translated Action Text`
|
* `action.<action-id>.<place>.text=Place-dependent Translated Action Text`
|
||||||
* `action.<action-id>.<place>.description=Place-dependent Translated Action Description`
|
* `action.<action-id>.<place>.description=Place-dependent Translated Action Description`
|
||||||
|
|
||||||
For Groups, the `key` in the property files incorporates the group `id` in this specific structure:
|
For Groups, the `key` in the property files incorporates the group `id` in this specific structure:
|
||||||
* `group.<group-id>.text=Translated Group Text`
|
* `group.<group-id>.text=Translated Group Text`
|
||||||
* `group.<group-id>.description=Translated Group Description`
|
* `group.<group-id>.description=Translated Group Description`
|
||||||
|
|
||||||
See [Extending DefaultActionGroup](/tutorials/action_system/grouping_action.md#extending-defaultactiongroup) for a tutorial of localizing Actions and Groups.
|
See [Extending DefaultActionGroup](/tutorials/action_system/grouping_action.md#extending-defaultactiongroup) for a tutorial of localizing Actions and Groups.
|
||||||
|
|
||||||
#### Action Declaration Reference
|
#### Action Declaration Reference
|
||||||
The places where actions can appear are defined by constants in [`ActionPlaces`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java).
|
The places where actions can appear are defined by constants in [`ActionPlaces`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java).
|
||||||
Group IDs for the IntelliJ Platform are defined in [`PlatformActions.xml`](upsource:///platform/platform-resources/src/idea/PlatformActions.xml).
|
Group IDs for the IntelliJ Platform are defined in [`PlatformActions.xml`](upsource:///platform/platform-resources/src/idea/PlatformActions.xml).
|
||||||
|
|
||||||
This, and additional information can also be found by using the [Code Completion](https://www.jetbrains.com/help/idea/auto-completing-code.html#invoke-basic-completion), [Quick Definition](https://www.jetbrains.com/help/idea/viewing-reference-information.html#view-definition-symbols) and [Quick Documentation](https://www.jetbrains.com/help/idea/viewing-reference-information.html#inline-quick-documentation) features.
|
This, and additional information can also be found by using the [Code Completion](https://www.jetbrains.com/help/idea/auto-completing-code.html#invoke-basic-completion), [Quick Definition](https://www.jetbrains.com/help/idea/viewing-reference-information.html#view-definition-symbols) and [Quick Documentation](https://www.jetbrains.com/help/idea/viewing-reference-information.html#inline-quick-documentation) features.
|
||||||
|
|
||||||
@ -204,7 +205,7 @@ This, and additional information can also be found by using the [Code Completion
|
|||||||
<!-- Actions -->
|
<!-- Actions -->
|
||||||
<actions>
|
<actions>
|
||||||
<!-- The <action> element defines an action to register.
|
<!-- The <action> element defines an action to register.
|
||||||
The mandatory "id" attribute specifies a unique
|
The mandatory "id" attribute specifies a unique
|
||||||
identifier for the action.
|
identifier for the action.
|
||||||
The mandatory "class" attribute specifies the
|
The mandatory "class" attribute specifies the
|
||||||
FQN of the class implementing the action.
|
FQN of the class implementing the action.
|
||||||
@ -216,15 +217,15 @@ This, and additional information can also be found by using the [Code Completion
|
|||||||
which is displayed in the status bar when the action is focused.
|
which is displayed in the status bar when the action is focused.
|
||||||
The optional "icon" attribute specifies the icon which is
|
The optional "icon" attribute specifies the icon which is
|
||||||
displayed on the toolbar button or next to the menu item. -->
|
displayed on the toolbar button or next to the menu item. -->
|
||||||
<action id="VssIntegration.GarbageCollection" class="com.foo.impl.CollectGarbage" text="Garbage Collector: Collect _Garbage"
|
<action id="VssIntegration.GarbageCollection" class="com.foo.impl.CollectGarbage" text="Garbage Collector: Collect _Garbage"
|
||||||
description="Run garbage collector" icon="icons/garbage.png">
|
description="Run garbage collector" icon="icons/garbage.png">
|
||||||
<!-- The <override-text> element defines an alternate version of the text for the menu action.
|
<!-- The <override-text> element defines an alternate version of the text for the menu action.
|
||||||
The mandatory "text" attribute defines the text to be displayed for the action.
|
The mandatory "text" attribute defines the text to be displayed for the action.
|
||||||
The mandatory "place" attribute declares where the alternate text should be used. In this example,
|
The mandatory "place" attribute declares where the alternate text should be used. In this example,
|
||||||
any time the action is displayed in the IDE Main Menu (and submenus) the override-text
|
any time the action is displayed in the IDE Main Menu (and submenus) the override-text
|
||||||
version should be used.
|
version should be used.
|
||||||
The second <override-text> element uses the alternate attribute "use-text-of-place" to define
|
The second <override-text> element uses the alternate attribute "use-text-of-place" to define
|
||||||
a location (EditorPopup) to use the same text as is used in MainMenu. It is a way to specify
|
a location (EditorPopup) to use the same text as is used in MainMenu. It is a way to specify
|
||||||
use of alternate menu text in multiple discrete menu groups. -->
|
use of alternate menu text in multiple discrete menu groups. -->
|
||||||
<override-text place="MainMenu" text="Collect _Garbage"/>
|
<override-text place="MainMenu" text="Collect _Garbage"/>
|
||||||
<override-text place="EditorPopup" use-text-of-place="MainMenu"/>
|
<override-text place="EditorPopup" use-text-of-place="MainMenu"/>
|
||||||
@ -234,7 +235,7 @@ This, and additional information can also be found by using the [Code Completion
|
|||||||
to which the action is added.
|
to which the action is added.
|
||||||
The group must be implemented by an instance of the DefaultActionGroup class.
|
The group must be implemented by an instance of the DefaultActionGroup class.
|
||||||
The mandatory "anchor" attribute specifies the position of the
|
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".
|
"first", "last", "before" and "after".
|
||||||
The "relative-to-action" attribute is mandatory if the anchor
|
The "relative-to-action" attribute is mandatory if the anchor
|
||||||
is set to "before" and "after", and specifies the action before or after which
|
is set to "before" and "after", and specifies the action before or after which
|
||||||
@ -249,12 +250,12 @@ This, and additional information can also be found by using the [Code Completion
|
|||||||
keystroke of the action.
|
keystroke of the action.
|
||||||
The mandatory "keymap" attribute specifies the keymap for which
|
The mandatory "keymap" attribute specifies the keymap for which
|
||||||
the action is active. IDs of the standard keymaps are defined as
|
the action is active. IDs of the standard keymaps are defined as
|
||||||
constants in the com.intellij.openapi.keymap.KeymapManager class.
|
constants in the com.intellij.openapi.keymap.KeymapManager class.
|
||||||
The optional "remove" attribute in the second <keyboard-shortcut>
|
The optional "remove" attribute in the second <keyboard-shortcut>
|
||||||
element below means the specified shortcut should be removed from
|
element below means the specified shortcut should be removed from
|
||||||
the specified action.
|
the specified action.
|
||||||
The optional "replace-all" attribute in the third <keyboard-shortcut>
|
The optional "replace-all" attribute in the third <keyboard-shortcut>
|
||||||
element below means remove all keyboard and mouse shortcuts from the specified
|
element below means remove all keyboard and mouse shortcuts from the specified
|
||||||
action before adding the specified shortcut. -->
|
action before adding the specified shortcut. -->
|
||||||
<!-- Add the first and second keystrokes to all keymaps -->
|
<!-- Add the first and second keystrokes to all keymaps -->
|
||||||
<keyboard-shortcut keymap="$default" first-keystroke="control alt G" second-keystroke="C"/>
|
<keyboard-shortcut keymap="$default" first-keystroke="control alt G" second-keystroke="C"/>
|
||||||
@ -266,7 +267,7 @@ This, and additional information can also be found by using the [Code Completion
|
|||||||
action. An action can have several mouse shortcuts.
|
action. An action can have several mouse shortcuts.
|
||||||
The mandatory "keystroke" attribute specifies the clicks and
|
The mandatory "keystroke" attribute specifies the clicks and
|
||||||
modifiers for the action. It is defined as a sequence of words
|
modifiers for the action. It is defined as a sequence of words
|
||||||
separated by spaces:
|
separated by spaces:
|
||||||
"button1", "button2", "button3" for the mouse buttons;
|
"button1", "button2", "button3" for the mouse buttons;
|
||||||
"shift", "control", "meta", "alt", "altGraph" for the modifier keys;
|
"shift", "control", "meta", "alt", "altGraph" for the modifier keys;
|
||||||
"doubleClick" if the action is activated by a double-click of the button.
|
"doubleClick" if the action is activated by a double-click of the button.
|
||||||
@ -277,13 +278,13 @@ This, and additional information can also be found by using the [Code Completion
|
|||||||
a <mouse-shortcut> element. See <keyboard-shortcut> for documentation. -->
|
a <mouse-shortcut> element. See <keyboard-shortcut> for documentation. -->
|
||||||
<mouse-shortcut keymap="$default" keystroke="control button3 doubleClick"/>
|
<mouse-shortcut keymap="$default" keystroke="control button3 doubleClick"/>
|
||||||
</action>
|
</action>
|
||||||
<!-- This action declares neither a text nor description attribute. If it has
|
<!-- This action declares neither a text nor description attribute. If it has
|
||||||
a resource bundle declared the text and descriptions will be retrieved
|
a resource bundle declared the text and descriptions will be retrieved
|
||||||
based on the action-id incorporated in the key for a translated string -->
|
based on the action-id incorporated in the key for a translated string -->
|
||||||
<action id="sdk.action.PopupDialogAction" class="sdk.action.PopupDialogAction"
|
<action id="sdk.action.PopupDialogAction" class="sdk.action.PopupDialogAction"
|
||||||
icon="SdkIcons.Sdk_default_icon">
|
icon="SdkIcons.Sdk_default_icon">
|
||||||
</action>
|
</action>
|
||||||
<!-- The <group> element defines an action group. <action>, <group> and
|
<!-- The <group> element defines an action group. <action>, <group> and
|
||||||
<separator> elements defined within it are automatically included in the group.
|
<separator> elements defined within it are automatically included in the group.
|
||||||
The mandatory "id" attribute specifies a unique identifier for the action.
|
The mandatory "id" attribute specifies a unique identifier for the action.
|
||||||
The optional "class" attribute specifies the FQN of
|
The optional "class" attribute specifies the FQN of
|
||||||
@ -298,7 +299,7 @@ This, and additional information can also be found by using the [Code Completion
|
|||||||
The optional "popup" attribute specifies how the group is presented in
|
The optional "popup" attribute specifies how the group is presented in
|
||||||
the menu. If a group has popup="true", actions in it are placed in a
|
the menu. If a group has popup="true", actions in it are placed in a
|
||||||
submenu; for popup="false", actions are displayed as a section of the
|
submenu; for popup="false", actions are displayed as a section of the
|
||||||
same menu delimited by separators.
|
same menu delimited by separators.
|
||||||
The optional "compact" attribute specifies whether an action within that group is visible when disabled.
|
The optional "compact" attribute specifies whether an action within that group is visible when disabled.
|
||||||
Setting compact="true" specifies an action in the group isn't visible unless the action is enabled. -->
|
Setting compact="true" specifies an action in the group isn't visible unless the action is enabled. -->
|
||||||
<group class="com.foo.impl.MyActionGroup" id="TestActionGroup" text="Test Group" description="Group with test actions" icon="icons/testgroup.png" popup="true" compact="true">
|
<group class="com.foo.impl.MyActionGroup" id="TestActionGroup" text="Test Group" description="Group with test actions" icon="icons/testgroup.png" popup="true" compact="true">
|
||||||
@ -317,14 +318,14 @@ This, and additional information can also be found by using the [Code Completion
|
|||||||
|
|
||||||
### Registering Actions from Code
|
### Registering Actions from Code
|
||||||
Two steps are required to register an action from code:
|
Two steps are required to register an action from code:
|
||||||
* First, an instance of the class derived from `AnAction` must be passed to the `registerAction()` method of [`ActionManager`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionManager.java), to associate the action with an ID.
|
* First, an instance of the class derived from `AnAction` must be passed to the `registerAction()` method of [`ActionManager`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionManager.java), to associate the action with an ID.
|
||||||
* Second, the action needs to be added to one or more groups.
|
* Second, the action needs to be added to one or more groups.
|
||||||
To get an instance of an action group by ID, it is necessary to call `ActionManager.getAction()` and cast the returned value to [`DefaultActionGroup`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java).
|
To get an instance of an action group by ID, it is necessary to call `ActionManager.getAction()` and cast the returned value to [`DefaultActionGroup`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java).
|
||||||
|
|
||||||
## Building UI from Actions
|
## Building UI from Actions
|
||||||
If a plugin needs to include a toolbar or popup menu built from a group of actions in its user interface, that is accomplished through [`ActionPopupMenu`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionPopupMenu.java) and [`ActionToolbar`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionToolbar.java).
|
If a plugin needs to include a toolbar or popup menu built from a group of actions in its user interface, that is accomplished through [`ActionPopupMenu`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionPopupMenu.java) and [`ActionToolbar`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionToolbar.java).
|
||||||
These objects can be created through calls to the `ActionManager.createActionPopupMenu()` and `createActionToolbar()` methods.
|
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.
|
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.
|
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 state of the toolbar buttons depends on the state of the related component, and not on the current focus location within the IDE frame.
|
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.
|
||||||
|
@ -3,7 +3,7 @@ title: Documents
|
|||||||
---
|
---
|
||||||
<!-- 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 [`Document`](upsource:///platform/core-api/src/com/intellij/openapi/editor/Document.java) is an editable sequence of Unicode characters, typically corresponding to the text contents of a [virtual file](virtual_file.md).
|
A [`Document`](upsource:///platform/core-api/src/com/intellij/openapi/editor/Document.java) is an editable sequence of Unicode characters, typically corresponding to the text contents of a [virtual file](virtual_file.md).
|
||||||
|
|
||||||
Line breaks in a document are _always_ normalized to `\n`.
|
Line breaks in a document are _always_ normalized to `\n`.
|
||||||
The *IntelliJ Platform* handles encoding and line break conversions when loading and saving documents transparently.
|
The *IntelliJ Platform* handles encoding and line break conversions when loading and saving documents transparently.
|
||||||
@ -21,23 +21,23 @@ From a PSI file
|
|||||||
|
|
||||||
## What can I do with a Document?
|
## 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?
|
## 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.
|
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?
|
## How long does a Document persist?
|
||||||
|
|
||||||
Document instances are weakly referenced from `VirtualFile` instances.
|
Document instances are weakly referenced from `VirtualFile` instances.
|
||||||
Thus, an unmodified `Document` instance can be garbage-collected if no one references it, and a new instance is created if the document contents are reaccessed later.
|
Thus, an unmodified `Document` instance can be garbage-collected if no one references it, and a new instance is created if the document contents are reaccessed later.
|
||||||
|
|
||||||
> **WARNING** Storing `Document` references in long-term data structures of a plugin will cause memory leaks.
|
> **WARNING** Storing `Document` references in long-term data structures of a plugin will cause memory leaks.
|
||||||
|
|
||||||
## How do I create a Document?
|
## How do I create a Document?
|
||||||
|
|
||||||
For creating a new file on disk, please do not create a `Document` but a PSI file and get its `Document`.
|
For creating a new file on disk, please do not create a `Document` but a PSI file and get its `Document`.
|
||||||
To create a `Document` instance that isn't bound to anything, use `EditorFactory.createDocument()`.
|
To create a `Document` instance that isn't bound to anything, use `EditorFactory.createDocument()`.
|
||||||
|
|
||||||
## How do I get notified when Documents change?
|
## How do I get notified when Documents change?
|
||||||
@ -48,8 +48,9 @@ To create a `Document` instance that isn't bound to anything, use `EditorFactory
|
|||||||
|
|
||||||
## What are the rules of working with Documents?
|
## 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.
|
||||||
`executeCommand()` calls can be nested, and the outermost `executeCommand()` call is added to the undo stack.
|
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.
|
If multiple documents are modified within a command, undoing this command will, by default, show a confirmation dialog to the user.
|
||||||
|
|
||||||
If the file corresponding to a `Document` is read-only (for example, not checked out from the version control system), document modifications will fail.
|
If the file corresponding to a `Document` is read-only (for example, not checked out from the version control system), document modifications will fail.
|
||||||
@ -59,5 +60,6 @@ All text strings passed to `Document` modification methods (`setText()`, `insert
|
|||||||
|
|
||||||
## Are there any utilities available for working with Documents?
|
## 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.
|
[`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`.
|
||||||
|
@ -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)).
|
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?
|
## 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?
|
## 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 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)`
|
* 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?
|
## How do I extend the FileViewProvider?
|
||||||
@ -36,4 +37,4 @@ Register as follows in `plugin.xml`:
|
|||||||
</extensions>
|
</extensions>
|
||||||
```
|
```
|
||||||
|
|
||||||
Where `%file_type%` refers to the type of the file being created (for example, "JFS").
|
Where `%file_type%` refers to the type of the file being created (for example, "JFS").
|
||||||
|
@ -5,18 +5,18 @@ title: General Threading Rules
|
|||||||
|
|
||||||
## Read/Write Lock
|
## Read/Write Lock
|
||||||
|
|
||||||
In general, code-related data structures in the *IntelliJ Platform* are covered by a single reader/writer lock.
|
In general, code-related data structures in the *IntelliJ Platform* are covered by a single reader/writer lock.
|
||||||
|
|
||||||
You must not access the model outside a read or write action for the following subsystems:
|
You must not access the model outside a read or write action for the following subsystems:
|
||||||
- PSI
|
- PSI
|
||||||
- VFS
|
- VFS
|
||||||
- project root model.
|
- project root model.
|
||||||
|
|
||||||
**Reading** data is allowed from any thread.
|
**Reading** data is allowed from any thread.
|
||||||
Reading data from the UI thread does not require any special effort.
|
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()`.
|
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.
|
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()`.
|
**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).
|
Modifying the model is only allowed from write-safe contexts, including user actions and `invokeLater()` calls from them (see the next section).
|
||||||
@ -26,60 +26,56 @@ You may not modify PSI, VFS, or project model from inside UI renderers or `Swing
|
|||||||
## Modality and `invokeLater()`
|
## Modality and `invokeLater()`
|
||||||
|
|
||||||
To pass control from a background thread to the event dispatch thread, instead of the standard `SwingUtilities.invokeLater()`, plugins should use `ApplicationManager.getApplication().invokeLater()`.
|
To pass control from a background thread to the event dispatch thread, instead of the standard `SwingUtilities.invokeLater()`, plugins should use `ApplicationManager.getApplication().invokeLater()`.
|
||||||
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:
|
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`
|
`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()`
|
`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.
|
: 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
|
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()`
|
`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.
|
: 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.
|
||||||
|
|
||||||
If a UI thread activity needs to access [file-based index](/basics/indexing_and_psi_stubs.md) (e.g., it's doing any project-wide PSI analysis, resolves references, etc.), please use `DumbService.smartInvokeLater()`.
|
If a UI thread activity needs to access [file-based index](/basics/indexing_and_psi_stubs.md) (e.g., it's doing any project-wide PSI analysis, resolves references, etc.), please use `DumbService.smartInvokeLater()`.
|
||||||
That way, it is run after all possible indexing processes have been completed.
|
That way, it is run after all possible indexing processes have been completed.
|
||||||
|
|
||||||
|
|
||||||
## Background processes and `ProcessCanceledException`
|
## Background processes and `ProcessCanceledException`
|
||||||
|
|
||||||
Background progresses are managed by [`ProgressManager`](upsource:///platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java) class,
|
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.
|
||||||
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.
|
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()`.
|
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:
|
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.
|
||||||
e.g., set text or visible fraction of the work done.
|
|
||||||
|
|
||||||
Progress indicators also provide means to handle cancellation of background processes, either by the user (pressing _Cancel_ button)
|
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).
|
||||||
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 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).
|
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.
|
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.
|
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.
|
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.
|
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
|
## 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),
|
Background threads shouldn't take plain read actions for a long time.
|
||||||
it must be acquired as soon as possible. Otherwise, the UI will freeze until all background threads have released their read actions.
|
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.
|
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.
|
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
|
To achieve that, the lengthy background operation is started with a `ProgressIndicator`, and a dedicated listener cancels that indicator when write action is initiated.
|
||||||
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.
|
||||||
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:
|
There are two recommended ways of doing this:
|
||||||
|
|
||||||
* If on UI thread, call `ReadAction.nonBlocking()` which returns [`NonBlockingReadAction`](upsource:///platform/core-api/src/com/intellij/openapi/application/NonBlockingReadAction.java)
|
* If on UI thread, call `ReadAction.nonBlocking()` which returns [`NonBlockingReadAction`](upsource:///platform/core-api/src/com/intellij/openapi/application/NonBlockingReadAction.java)
|
||||||
|
@ -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. -->
|
<!-- 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
|
The PSI is a read-write representation of the source code as a tree of elements corresponding to a source file's structure.
|
||||||
file. You can modify the PSI by *adding*, *replacing*, and *deleting* PSI elements.
|
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()`,
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
|
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
|
## Creating the New PSI
|
||||||
|
|
||||||
The PSI elements to add to the tree, or to replace existing PSI elements, are normally *created from text*.
|
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)
|
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()`.
|
||||||
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()`.
|
|
||||||
|
|
||||||
Most languages provide factory methods which let you create specific code constructs more easily. For example,
|
Most languages provide factory methods that let you create specific code constructs more easily.
|
||||||
the [`PsiJavaParserFacade`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiJavaParserFacade.java) class
|
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.
|
||||||
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
|
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.
|
||||||
you pass to the various `createFromText()` methods will combine hard-coded fragments and fragments of code taken from
|
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.
|
||||||
the existing file. For small code fragments (individual identifiers), you can simply append the text from the existing
|
In that case, you need to make sure that the resulting text is syntactically correct. Otherwise the `createFromText()` method will throw an exception.
|
||||||
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:
|
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 placeholders with the user code fragments;
|
||||||
* replace the element in the original source file with the replacement tree.
|
* 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
|
This ensures that the user code's formatting is preserved and that the modification doesn't introduce any unwanted whitespace changes.
|
||||||
whitespace changes.
|
|
||||||
|
|
||||||
As an example of this approach, see the quickfix in the `ComparingReferencesInspection` example:
|
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);
|
PsiExpression result = (PsiExpression) binaryExpression.replace(equalsCall);
|
||||||
```
|
```
|
||||||
|
|
||||||
Just as everywhere else in the IntelliJ Platform API, the text passed to `createFileFromText()` and other `createFromText()`
|
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.
|
||||||
methods must use only `\n` as line separators.
|
|
||||||
|
|
||||||
|
|
||||||
## Maintaining Tree Structure Consistency
|
## Maintaining Tree Structure Consistency
|
||||||
|
|
||||||
The PSI modification methods do not restrict you in the way you can build the resulting tree structure. For example,
|
The PSI modification methods do not restrict you in the way you can build the resulting tree structure.
|
||||||
when working with a Java class, you can add a `for` statement as a direct child of a `PsiMethod` element, even though
|
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).
|
||||||
the Java parser will never produce such a structure (the `for` statement will always be a child of the `PsiCodeBlock`)
|
Modifications that produce incorrect tree structures may appear to work, but they will lead to problems and exceptions later.
|
||||||
representing the method body). Modifications that produce incorrect tree structures may appear to work, but they will
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
To make sure you're not introducing inconsistencies, you can call `PsiTestUtil.checkFileStructure()` in the tests for
|
To make sure you're not introducing inconsistencies, you can call `PsiTestUtil.checkFileStructure()` in the tests for your action that modifies the PSI.
|
||||||
your action that modifies the PSI. This method ensures that the structure you've built is the same as what the parser produces.
|
This method ensures that the structure you've built is the same as what the parser produces.
|
||||||
|
|
||||||
|
|
||||||
## Whitespaces and Imports
|
## Whitespaces and Imports
|
||||||
|
|
||||||
When working with PSI modification functions, you should never create individual whitespace nodes (spaces or line breaks)
|
When working with PSI modification functions, you should never create individual whitespace nodes (spaces or line breaks) from the text.
|
||||||
from text. Instead, all whitespace modifications are performed by the formatter, which follows the code style settings
|
Instead, all whitespace modifications are performed by the formatter, which follows the code style settings selected by the user.
|
||||||
selected by the user. Formatting is automatically performed at the end of every command, and if you need, you can
|
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 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),
|
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.
|
||||||
you should never create imports manually. Instead, you should insert fully-qualified names into the code you're
|
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).
|
||||||
generating, and then call the `shortenClassReferences()` method in the
|
This ensures that the imports are created according to the user's code style settings and inserted into the file's correct place.
|
||||||
[`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.
|
|
||||||
|
|
||||||
|
|
||||||
## Combining PSI and Document Modifications
|
## 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.
|
||||||
|
@ -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. -->
|
<!-- 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,
|
There are three main ways to navigate the PSI: *top-down*, *bottom-up*, and *references*.
|
||||||
you have a PSI file or another higher-level element (for example, a method), and you need to find all elements that match a
|
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).
|
||||||
specified condition (for example, all variable declarations). In the second scenario, you have a specific point
|
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).
|
||||||
in the PSI tree (for example, the element at caret) and need to find out something about its context (for example,
|
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.
|
||||||
the element in which it has been declared). Finally, *references* allow you to navigate from the use of an element
|
References are described in a [separate topic](psi_references.md).
|
||||||
(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
|
## 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
|
The most common way to perform top-down navigation is to use a *visitor*.
|
||||||
(usually an anonymous inner class) that extends the base visitor class, override the methods that handle the elements
|
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()`.
|
||||||
you're interested in, and pass the visitor instance it to `PsiElement.accept()`.
|
|
||||||
|
|
||||||
The base classes for visitors are language-specific. For example, if you need to process elements in a Java file,
|
The base classes for visitors are language-specific.
|
||||||
you extend `JavaRecursiveElementVisitor` and override the methods corresponding to the Java element types you're
|
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.
|
||||||
interested in.
|
|
||||||
|
|
||||||
The following snippet shows the use of a visitor to find all Java local variable declarations:
|
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
|
In many cases, you can also use more specific APIs for top-down navigation.
|
||||||
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()`.
|
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
|
[`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.
|
||||||
general-purpose, language-independent functions for PSI tree navigation, some of which (for example, `findChildrenOfType()`)
|
|
||||||
perform top-down navigation.
|
|
||||||
|
|
||||||
## Bottom-Up 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
|
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.
|
||||||
resolving a reference), or an offset. If you have an offset, you can find the corresponding PSI element by calling
|
If you have an offset, you can find the corresponding PSI element by calling `PsiFile.findElementAt()`.
|
||||||
`PsiFile.findElementAt()`. This method returns the element at the lowest level of the tree (for example, an identifier),
|
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.
|
||||||
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
|
In most cases, bottom-up navigation is performed by calling `PsiTreeUtil.getParentOfType()`.
|
||||||
tree until it finds the element of the type you've specified. For example, to find the containing method, you call
|
This method goes up the tree until it finds the element of the type you've specified.
|
||||||
`PsiTreeUtil.getParentOfType(element, PsiMethod.class)`.
|
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,
|
In some cases, you can also use specific navigation methods.
|
||||||
you call `PsiMethod.getContainingClass()`.
|
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:
|
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();
|
PsiClass containingClass = containingMethod.getContainingClass();
|
||||||
```
|
```
|
||||||
|
|
||||||
To see how the navigation works in practice, please refer to the
|
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).
|
||||||
[code sample](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/psi_demo/src/main/java/org/intellij/sdk/psi/PsiNavigationDemoAction.java).
|
|
||||||
|
@ -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. -->
|
<!-- 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)
|
* [PSI Files](/basics/architectural_overview/psi_files.md)
|
||||||
* [File View Providers](/basics/architectural_overview/file_view_providers.md)
|
* [File View Providers](/basics/architectural_overview/file_view_providers.md)
|
||||||
* [PSI Elements](/basics/architectural_overview/psi_elements.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).
|
> **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 structure of the PSI tree, the properties of every PSI element and highlight its text range.
|
> It can show you the PSI tree structure, the properties of every PSI element, and highlight its text range.
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
---
|
---
|
||||||
title: PSI Elements
|
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.
|
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?
|
## 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 an action: `e.getData(LangDataKeys.PSI_ELEMENT)`.
|
||||||
* 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.
|
Note: if an editor is currently open and the element under caret is a reference, this will return the result of resolving the reference.
|
||||||
Most likely you should use `PsiTreeUtil.getParentOfType()` to find the element you really need.
|
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 iterating through a PSI file: using a [`PsiRecursiveElementWalkingVisitor`](upsource:///platform/core-api/src/com/intellij/psi/PsiRecursiveElementWalkingVisitor.java).
|
||||||
* By resolving a reference: `PsiReference.resolve()`
|
* By resolving a reference: `PsiReference.resolve()`
|
||||||
|
|
||||||
|
@ -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. -->
|
<!-- 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.
|
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?
|
## 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.
|
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?
|
## 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?
|
## 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?
|
## What are the rules for working with PSI?
|
||||||
|
|
||||||
|
@ -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. -->
|
<!-- 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
|
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.
|
||||||
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
|
```java
|
||||||
public void hello(String message) {
|
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
|
This simple code fragment contains five references.
|
||||||
`println` can be resolved to the corresponding declarations in the JDK: the `String` and `System` classes, the `out` field and the
|
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.
|
||||||
`println` method. The reference created by the second occurrence of the `message` identifier in `println(message)` can be resolved to the
|
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.
|
||||||
`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
|
Note that `String message` is not a reference and cannot be resolved.
|
||||||
refer to any name defined elsewhere; instead, it defines a name by itself.
|
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.
|
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
|
Note that references are distinct from PSI elements.
|
||||||
`PsiElement.getReferences()`, the underlying PSI element of a reference can be obtained from `PsiReference.getElement()`.
|
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
|
To *resolve* the reference - to locate the declaration being referenced - call `PsiReference.resolve()`.
|
||||||
important to understand the difference between `PsiReference.getElement()` and `PsiReference.resolve()`. The former method returns the _source_
|
It's very important to understand the difference between `PsiReference.getElement()` and `PsiReference.resolve()`.
|
||||||
of a reference, while the latter returns its _target_. In the example above, for the `message` reference, `getElement()`
|
The former method returns the _source_ of a reference, while the latter returns its _target_.
|
||||||
will return the `message` identifier on the second line of the snippet, and `resolve()` will return the `message` identifier
|
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).
|
||||||
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
|
The process of resolving references is distinct from parsing and is not performed at the same time.
|
||||||
not always successful. If the code currently open in the IDE does not compile, or in other situations, it's normal
|
Moreover, it is not always successful.
|
||||||
for `PsiReference.resolve()` to return `null` - all code working with references must be prepared to handle that.
|
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).
|
> **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
|
## Contributed References
|
||||||
|
|
||||||
In addition to references defined by the semantics of the programming language, the IDE recognizes many references
|
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.
|
||||||
which are determined by the semantics of the APIs and frameworks used in code. Consider the following example:
|
Consider the following example:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
File f = new File("foo.txt");
|
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,
|
Here, "foo.txt" has no special meaning from the point of view of the Java syntax - it's just a string literal.
|
||||||
opening this example in IntelliJ IDEA and having a file called "foo.txt" in the same directory, one
|
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.
|
||||||
can <kbd>Ctrl/Cmd</kbd>-Click on "foo.txt" and navigate to the file. This works because the IDE recognizes the
|
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.
|
||||||
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
|
Typically, references can be contributed to elements that don't have their own references, such as string literals and comments.
|
||||||
and comments. References are also often contributed to non-code files, such as XML or JSON.
|
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
|
Contributing references is one of the most common ways to extend an existing language.
|
||||||
contribute references to Java code, even though the Java PSI is part of the platform and not defined in your plugin.
|
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).
|
To contribute references, see the [reference contributor tutorial](/tutorials/custom_language_support/reference_contributor.md).
|
||||||
|
|
||||||
|
|
||||||
## References with Optional or Multiple Resolve Results
|
## References with Optional or Multiple Resolve Results
|
||||||
|
|
||||||
In the simplest case, a reference resolves to a single element, and if resolving fails, the
|
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.
|
||||||
code is incorrect, and the IDE needs to highlight it as an error. However, there are cases when the situation is different.
|
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 first case is *soft references*.
|
||||||
the file "foo.txt", it doesn't mean that an error needs to be highlighted - maybe the file is only available at runtime.
|
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.
|
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
|
The second case is *polyvariant references*.
|
||||||
typed language, so the IDE cannot always precisely determine which method is being called at a particular location.
|
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.
|
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.
|
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
|
For resolving a `PsiPolyVariantReference`, you call its `multiResolve()` method.
|
||||||
[`ResolveResult`](upsource:///platform/core-api/src/com/intellij/psi/ResolveResult.java) objects. Each of the
|
The call returns an array of [`ResolveResult`](upsource:///platform/core-api/src/com/intellij/psi/ResolveResult.java) objects.
|
||||||
objects identifies a PSI element and also specifies whether the result is valid. For example, if you have multiple
|
Each of the objects identifies a PSI element and also specifies whether the result is valid.
|
||||||
Java method overloads and a call with arguments not matching any of the overloads, you will get
|
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.
|
||||||
back `ResolveResult` objects for all of the overloads, and `isValidResult()` returns `false` for all of them.
|
|
||||||
|
|
||||||
|
|
||||||
## Searching for References
|
## Searching for References
|
||||||
|
|
||||||
As you already know, resolving a reference means going from usage to the corresponding declaration. To perform the
|
As you already know, resolving a reference means going from usage to the corresponding declaration.
|
||||||
navigation in the opposite direction - from a declaration to its usages - perform a **references search**.
|
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
|
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.
|
||||||
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
|
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.
|
||||||
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.
|
The latter allows stopping processing as soon as the first (matching) result has been found.
|
||||||
|
|
||||||
## Implementing References
|
## Implementing References
|
||||||
|
|
||||||
Please refer to the [guide](/reference_guide/custom_language_support/references_and_resolve.md) and
|
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.
|
||||||
corresponding [tutorial](/tutorials/custom_language_support/reference_contributor.md) for more information.
|
|
||||||
|
@ -5,17 +5,18 @@ title: Virtual Files
|
|||||||
|
|
||||||
A [`VirtualFile`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java) (VF) is the *IntelliJ Platform's* representation of a file in a [Virtual File System (VFS)](/basics/virtual_file_system.md).
|
A [`VirtualFile`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java) (VF) is the *IntelliJ Platform's* representation of a file in a [Virtual File System (VFS)](/basics/virtual_file_system.md).
|
||||||
|
|
||||||
Most commonly, a virtual file is a file in a local file system.
|
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.
|
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?
|
## How do I get a virtual file?
|
||||||
|
|
||||||
From an action
|
From an action
|
||||||
: `e.getData(PlatformDataKeys.VIRTUAL_FILE)` or `e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY)` for multiple selection
|
: `e.getData(PlatformDataKeys.VIRTUAL_FILE)` or `e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY)` for multiple selection
|
||||||
|
|
||||||
From a path in the local file system:
|
From a path in the local file system:
|
||||||
: - `LocalFileSystem.getInstance().findFileByIoFile()`
|
: - `LocalFileSystem.getInstance().findFileByIoFile()`
|
||||||
- `VirtualFileManager.findFileByNioPath()`/`refreshAndFindFileByNioPath()` (2020.2 and later)
|
- `VirtualFileManager.findFileByNioPath()`/`refreshAndFindFileByNioPath()` (2020.2 and later)
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ From a document
|
|||||||
|
|
||||||
## What can I do with it?
|
## What can I do with it?
|
||||||
|
|
||||||
Typical file operations are available, such as traverse the file system, get file contents, rename, move, or delete.
|
Typical file operations are available, such as traverse the file system, get file contents, rename, move, or delete.
|
||||||
Recursive iteration should be performed using `VfsUtilCore.iterateChildrenRecursively()` to prevent endless loops caused by recursive symlinks.
|
Recursive iteration should be performed using `VfsUtilCore.iterateChildrenRecursively()` to prevent endless loops caused by recursive symlinks.
|
||||||
|
|
||||||
## Where does it come from?
|
## Where does it come from?
|
||||||
@ -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?
|
## 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.
|
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.
|
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.
|
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?
|
## 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.
|
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.
|
> **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
|
```java
|
||||||
project.getMessageBus().connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
|
project.getMessageBus().connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
|
||||||
|
@ -7,10 +7,10 @@ The IntelliJ Platform's [`Disposer`](upsource:///platform/util/src/com/intellij/
|
|||||||
If a subsystem keeps a set of resources alive coincident with a parent object's lifetime, the subsystem's resources should be registered with the `Disposer` to be released before or at the same time as the parent object.
|
If a subsystem keeps a set of resources alive coincident with a parent object's lifetime, the subsystem's resources should be registered with the `Disposer` to be released before or at the same time as the parent object.
|
||||||
|
|
||||||
The most common resource type managed by `Disposer` is listeners, but there are other possible types:
|
The most common resource type managed by `Disposer` is listeners, but there are other possible types:
|
||||||
* File handles, and database connections,
|
* File handles, and database connections,
|
||||||
* Caches and other significant data structures.
|
* Caches and other significant data structures.
|
||||||
|
|
||||||
The `Disposer` is a singleton that manages a tree of [`Disposable`](upsource:///platform/util/src/com/intellij/openapi/Disposable.java) instances.
|
The `Disposer` is a singleton that manages a tree of [`Disposable`](upsource:///platform/util/src/com/intellij/openapi/Disposable.java) instances.
|
||||||
A `Disposable` is an interface for any object providing a `Disposable.dispose()` method to release heavyweight resources after a specific lifetime.
|
A `Disposable` is an interface for any object providing a `Disposable.dispose()` method to release heavyweight resources after a specific lifetime.
|
||||||
|
|
||||||
The `Disposer` supports chaining `Disposables` in parent-child relationships.
|
The `Disposer` supports chaining `Disposables` in parent-child relationships.
|
||||||
@ -19,21 +19,20 @@ The `Disposer` supports chaining `Disposables` in parent-child relationships.
|
|||||||
|
|
||||||
## Automatically Disposed Objects
|
## Automatically Disposed Objects
|
||||||
|
|
||||||
A number of objects are disposed automatically by the platform if they implement the `Disposable` interface.
|
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
|
The most important type of such objects is [services](/basics/plugin_structure/plugin_services.md).
|
||||||
services are automatically disposed by the platform when the IDE is closed, or the plugin providing the service is
|
Application-level services are automatically disposed by the platform when the IDE is closed or the plugin providing the service is unloaded.
|
||||||
unloaded. Project-level services are disposed when the project is closed or the plugin 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
|
Note that extensions registered in `plugin.xml` are *not* automatically disposed.
|
||||||
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
|
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.
|
||||||
disposable.
|
|
||||||
|
|
||||||
|
|
||||||
## The Disposer Singleton
|
## The Disposer Singleton
|
||||||
The primary purpose of the [`Disposer`](upsource:///platform/util/src/com/intellij/openapi/util/Disposer.java) singleton is to enforce the rule that _a child `Disposable` never outlives its parent_.
|
The primary purpose of the [`Disposer`](upsource:///platform/util/src/com/intellij/openapi/util/Disposer.java) singleton is to enforce the rule that _a child `Disposable` never outlives its parent_.
|
||||||
|
|
||||||
The `Disposer` organizes `Disposable` objects in a tree of parent-child relationships.
|
The `Disposer` organizes `Disposable` objects in a tree of parent-child relationships.
|
||||||
The tree of `Disposable` objects ensures the `Disposer` releases children of a parent first.
|
The tree of `Disposable` objects ensures the `Disposer` releases children of a parent first.
|
||||||
|
|
||||||
See [The Disposable Interface](#implementing-the-disposable-interface) for more information about creating `Disposable` classes.
|
See [The Disposable Interface](#implementing-the-disposable-interface) for more information about creating `Disposable` classes.
|
||||||
|
|
||||||
@ -42,7 +41,7 @@ Registering a disposable is performed by calling `Disposer.register()`:
|
|||||||
```java
|
```java
|
||||||
Disposer.register(parentDisposable, childDisposable);
|
Disposer.register(parentDisposable, childDisposable);
|
||||||
```
|
```
|
||||||
|
|
||||||
### Choosing a Disposable Parent
|
### Choosing a Disposable Parent
|
||||||
|
|
||||||
To register a child `Disposable`, a parent `Disposable` of a suitable lifetime is used to establish the parent-child relationship.
|
To register a child `Disposable`, a parent `Disposable` of a suitable lifetime is used to establish the parent-child relationship.
|
||||||
@ -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:
|
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 [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 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
|
* For resources with a shorter lifetime, create a disposable using `Disposer.newDisposable()` and dispose it manually using `Disposable.dispose()`.
|
||||||
using `Disposable.dispose()`. Note that it's always best to specify a parent for such a disposable (e.g., a project-level service),
|
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.
|
||||||
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.
|
> **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.
|
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.
|
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 as a result of each invocation.
|
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.
|
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,
|
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.
|
||||||
the entire component will remain in memory after the operation is complete. This creates memory pressure and can waste
|
This creates memory pressure and can waste CPU cycles on processing events that are no longer relevant.
|
||||||
CPU cycles on processing events that are no longer relevant for anything.
|
|
||||||
|
|
||||||
### Registering Listeners with Parent Disposable
|
### Registering Listeners with Parent Disposable
|
||||||
|
|
||||||
Many IntelliJ Platform APIs for registering listeners either require passing a parent disposable or have overloads that
|
Many IntelliJ Platform APIs for registering listeners either require passing a parent disposable or have overloads that take a parent disposable.
|
||||||
take a parent disposable. For example:
|
For example:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public abstract class EditorFactory {
|
public abstract class EditorFactory {
|
||||||
@ -82,39 +79,38 @@ public abstract class EditorFactory {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Methods with a `parentDisposable` parameter automatically unsubscribe the listener when the corresponding parent disposable
|
Methods with a `parentDisposable` parameter automatically unsubscribe the listener when the corresponding parent disposable is disposed.
|
||||||
is disposed. Using such methods is always preferable to removing listeners explicitly from the `dispose` method, because
|
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.
|
||||||
it requires less code and is easier to verify for correctness.
|
|
||||||
|
|
||||||
To choose the correct parent disposable, use the guidelines from the previous section.
|
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
|
The same rules apply to [message bus](/reference_guide/messaging_infrastructure.md) connections.
|
||||||
it has the shortest possible lifetime.
|
Always pass a parent disposable to `MessageBus.connect()`, and make sure it has the shortest possible lifetime.
|
||||||
|
|
||||||
### Determining Disposal Status
|
### Determining Disposal Status
|
||||||
You can use `Disposer.isDisposed()` to check whether a `Disposable` has already been disposed.
|
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.
|
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.
|
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
|
### Ending a Disposable Lifecycle
|
||||||
A plugin can manually end a `Disposable` lifecycle by calling `Disposer.dispose(Disposable)`.
|
A plugin can manually end a `Disposable` lifecycle by calling `Disposer.dispose(Disposable)`.
|
||||||
This method handles recursively disposing of all the `Disposable` child descendants as well.
|
This method handles recursively disposing of all the `Disposable` child descendants as well.
|
||||||
|
|
||||||
## Implementing the Disposable Interface
|
## Implementing the Disposable Interface
|
||||||
|
|
||||||
Creating a class requires implementing the `Disposable` interface and defining the `dispose()` method.
|
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
|
In many cases, when the object implements `Disposable` only to be used as a parent disposable, the method's implementation will be completely empty.
|
||||||
method will be completely empty.
|
|
||||||
|
|
||||||
An example of a non-trivial `dispose` implementation is shown below:
|
An example of a non-trivial `dispose` implementation is shown below:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class Foo<T> extends JBFoo implements Disposable {
|
public class Foo<T> extends JBFoo implements Disposable {
|
||||||
public Foo(@NotNull Project project, @NotNull String name, @Nullable FileEditor fileEditor, @NotNull Disposable parentDisposable) {
|
public Foo(@NotNull Project project, @NotNull String name, @Nullable FileEditor fileEditor, @NotNull Disposable parentDisposable) {
|
||||||
this(project, name, fileEditor, InitParams.createParams(project), DetachedToolWindowManager.getInstance(project));
|
this(project, name, fileEditor, InitParams.createParams(project), DetachedToolWindowManager.getInstance(project));
|
||||||
Disposer.register(parentDisposable, this);
|
Disposer.register(parentDisposable, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,11 +131,12 @@ Regardless, it illustrates the basic pattern, which is:
|
|||||||
* The `Foo` disposable is registered as a child of `parentDisposable` in the constructor.
|
* 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`.
|
* 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
|
## Diagnosing Disposer Leaks
|
||||||
|
|
||||||
When the application exits, it performs a final sanity check to verify everything was disposed.
|
When the application exits, it performs a final sanity check to verify everything was disposed.
|
||||||
If something was registered with the `Disposer` but remains undisposed, the IntelliJ Platform reports it before shutting down.
|
If something was registered with the `Disposer` but remains undisposed, the IntelliJ Platform reports it before shutting down.
|
||||||
|
|
||||||
In test and Debug mode (`idea.disposer.debug` is set to `on`), registering a `Disposable` with the `Disposer` also registers a stack trace for the object's allocation path.
|
In test and Debug mode (`idea.disposer.debug` is set to `on`), registering a `Disposable` with the `Disposer` also registers a stack trace for the object's allocation path.
|
||||||
@ -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.
|
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.
|
In turn, that code allocated a `Project` that was never disposed by the time the application exited.
|
||||||
That is a promising initial place to start digging.
|
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.
|
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.
|
||||||
|
@ -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. -->
|
<!-- 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
|
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).
|
||||||
[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
|
## Open-Source Plugins
|
||||||
* [How do I compile the Scala plugin?](https://github.com/jetbrains/intellij-scala#setting-up-the-project)
|
* [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 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 "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 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 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-)
|
* [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-)
|
* [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-)
|
||||||
|
@ -3,13 +3,16 @@ 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. -->
|
<!-- 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.
|
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.
|
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.
|
||||||
The old [Plugin DevKit](#using-devkit) workflow still supports existing projects.
|
The old [Plugin DevKit](#using-devkit) workflow still supports existing projects.
|
||||||
|
|
||||||
> **NOTE** If a new plugin will be Scala-based, a dedicated SBT plugin [sbt-idea-plugin](https://github.com/JetBrains/sbt-idea-plugin) is available.
|
> **NOTE** If a new plugin will be Scala-based, a dedicated SBT plugin [sbt-idea-plugin](https://github.com/JetBrains/sbt-idea-plugin) is available.
|
||||||
|
|
||||||
The Gradle workflow offers several advantages:
|
The Gradle workflow offers several advantages:
|
||||||
* Representations of source sets, modules, and projects are portable,
|
* Representations of source sets, modules, and projects are portable,
|
||||||
@ -21,7 +24,7 @@ Specific to development of IntelliJ Platform plugins with the Gradle plugin for
|
|||||||
* Switching the version of the target IntelliJ Platform (IDE),
|
* Switching the version of the target IntelliJ Platform (IDE),
|
||||||
* Changing the target IntelliJ Platform-based IDE, e.g., from IntelliJ IDEA to PyCharm,
|
* Changing the target IntelliJ Platform-based IDE, e.g., from IntelliJ IDEA to PyCharm,
|
||||||
* Running a plugin against alternate versions of the JetBrains runtime.
|
* Running a plugin against alternate versions of the JetBrains runtime.
|
||||||
* Gradle is fully integrated with Continuous Integration systems and [JetBrains Plugin Repository](https://plugins.jetbrains.com), so it is easy to customize and extend the build and publishing processes.
|
* Gradle is fully integrated with Continuous Integration systems and [JetBrains Plugin Repository](https://plugins.jetbrains.com), so it is easy to customize and extend the build and publishing processes.
|
||||||
* Built-in verification task for `plugin.xml` and plugin distribution structure, the same checks as on [JetBrains Plugin Repository](https://plugins.jetbrains.com).
|
* Built-in verification task for `plugin.xml` and plugin distribution structure, the same checks as on [JetBrains Plugin Repository](https://plugins.jetbrains.com).
|
||||||
|
|
||||||
## Using GitHub Template
|
## Using GitHub Template
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
title: Build Number Ranges
|
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>
|
<style>
|
||||||
table {
|
table {
|
||||||
width:100%;
|
width:100%;
|
||||||
@ -12,7 +13,7 @@ title: Build Number Ranges
|
|||||||
|
|
||||||
Use this reference of build number ranges to specify the correct `since-build` and `until-build` values in your plugin descriptor.
|
Use this reference of build number ranges to specify the correct `since-build` and `until-build` values in your plugin descriptor.
|
||||||
|
|
||||||
When using Gradle, setting the actual values in `plugin.xml` is usually managed by the `patchPluginXml` task, see [Patching the Plugin Configuration File](/tutorials/build_system/gradle_guide.md#patching-the-plugin-configuration-file) for details.
|
When using Gradle, setting the actual values in `plugin.xml` is usually managed by the `patchPluginXml` task, see [Patching the Plugin Configuration File](/tutorials/build_system/gradle_guide.md#patching-the-plugin-configuration-file) for details.
|
||||||
|
|
||||||
> **NOTE** Compatibility with specified version range (and compatible products) should always be verified using [Plugin Verifier](/reference_guide/api_changes_list.md#verifying-compatibility) to ensure binary compatibility.
|
> **NOTE** Compatibility with specified version range (and compatible products) should always be verified using [Plugin Verifier](/reference_guide/api_changes_list.md#verifying-compatibility) to ensure binary compatibility.
|
||||||
|
|
||||||
@ -24,11 +25,17 @@ The number consists of the following parts:
|
|||||||
* Branch number (`162`)
|
* Branch number (`162`)
|
||||||
* Build number in the branch (`94`)
|
* 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
|
```xml
|
||||||
<idea-version since-build="94.539"/>
|
<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 |
|
| [163](https://github.com/JetBrains/intellij-community/tree/163) | 2016.3 |
|
||||||
| [162](https://github.com/JetBrains/intellij-community/tree/162) | 2016.2 |
|
| [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
|
### IntelliJ Platform Based Products of Pre-2016.2 IDE Versions
|
||||||
|
|
||||||
|
@ -7,34 +7,31 @@ redirect_from:
|
|||||||
|
|
||||||
> **NOTE** For new projects, it is highly recommended to use [Gradle](/tutorials/build_system.md).
|
> **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).
|
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:
|
### To Create an IntelliJ Platform Plugin Project:
|
||||||
|
|
||||||
* On the main menu, choose **File \| New \| Project**. The *New Project*
|
* On the main menu, choose **File \| New \| Project**.
|
||||||
wizard starts.
|
The *New Project* wizard starts.
|
||||||
|

|
||||||

|
* Set *IntelliJ Platform Plugin* project type.
|
||||||
|
* Click **Next**.
|
||||||
* Set *IntelliJ Platform Plugin* project type.
|
* Set the desired project name.
|
||||||
* Click **Next**.
|
* Click **Finish** to generate project structure files.
|
||||||
* Set the desired project name.
|
* Go to **File \| Project Structure** to customize project settings if required.
|
||||||
* Click **Finish** to generate project structure files.
|
|
||||||
* Go to **File \| Project Structure** to customize project settings if required.
|
|
||||||
|
|
||||||
### To Create an IntelliJ Platform Plugin Module
|
### To Create an IntelliJ Platform Plugin Module
|
||||||
* Select **File \| New \| Module** and choose the *IntelliJ Platform Plugin* module type
|
* Select **File \| New \| Module** and choose the *IntelliJ Platform Plugin* module type
|
||||||
|

|
||||||

|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
* Enter your desired plugin name.
|
||||||
* 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:
|
||||||
|

|
||||||
* Go to **File \| Project Structure** and select the newly created *IntelliJ Platform SDK* as the default SDK for the plugin module:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Adding Code to the Project
|
### Adding Code to the Project
|
||||||
Before running the new project, add some code to provide simple functionality.
|
Before running the new project, add some code to provide simple functionality.
|
||||||
See the [Creating Actions](/tutorials/action_system/working_with_custom_actions.md) tutorial for step-by-step instructions for adding a menu action.
|
See the [Creating Actions](/tutorials/action_system/working_with_custom_actions.md) tutorial for step-by-step instructions for adding a menu action.
|
||||||
|
@ -8,18 +8,20 @@ Before your custom plugin can be used, it must be deployed: built, installed, an
|
|||||||
To deploy a plugin:
|
To deploy a plugin:
|
||||||
|
|
||||||
* Make your project by invoking **Build \| Build Project** or **Build \| Build Module \<module name\>**.
|
* 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**.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
* 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.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
* [Install](https://www.jetbrains.com/help/idea/managing-plugins.html#installing-plugins-from-disk)
|
* [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:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
* Restart your IDE so the changes will take effect.
|
* Restart your IDE so the changes will take effect.
|
||||||
|
|
||||||
|
@ -13,46 +13,46 @@ title: Plugin Compatibility with IntelliJ Platform Products
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
All products based on the _IntelliJ Platform_ are built on the same underlying API.
|
All products based on the _IntelliJ Platform_ are built on the same underlying API.
|
||||||
Some of these products share features built on top of the platform, such as Java support in IntelliJ IDEA and Android Studio.
|
Some of these products share features built on top of the platform, such as Java support in IntelliJ IDEA and Android Studio.
|
||||||
Underlying those shared features are shared components.
|
Underlying those shared features are shared components.
|
||||||
When authoring a plugin for the IntelliJ Platform, it is important to understand and declare dependencies on these components.
|
When authoring a plugin for the IntelliJ Platform, it is important to understand and declare dependencies on these components.
|
||||||
Otherwise, it may not be possible to load or run the plugin in a product because the components on which it depends aren't available.
|
Otherwise, it may not be possible to load or run the plugin in a product because the components on which it depends aren't available.
|
||||||
|
|
||||||
> **TIP** Qualifying Open Source projects can [apply for free licenses](https://www.jetbrains.com/community/opensource/) of JetBrains products.
|
> **TIP** Qualifying Open Source projects can [apply for free licenses](https://www.jetbrains.com/community/opensource/) of JetBrains products.
|
||||||
|
|
||||||
* bullet list
|
* bullet list
|
||||||
{:toc}
|
{:toc}
|
||||||
|
|
||||||
## Declaring Plugin Dependencies
|
## Declaring Plugin Dependencies
|
||||||
For the purposes of dependencies, a _module_ can be thought of like a built-in plugin that ships as a non-removable part of a product.
|
For the purposes of dependencies, a _module_ can be thought of like a built-in plugin that ships as a non-removable part of a product.
|
||||||
A working definition of a dependency is that a plugin project cannot be run without the module present in an IntelliJ Platform-based product.
|
A working definition of a dependency is that a plugin project cannot be run without the module present in an IntelliJ Platform-based product.
|
||||||
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.
|
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 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:
|
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.
|
* 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.
|
* 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
|
## Modules
|
||||||
A _module_ represents a built-in plugin that is a non-removable part of a product.
|
A _module_ represents a built-in plugin that is a non-removable part of a product.
|
||||||
Some modules are available in all products, and some modules are available only in some, or even just one product.
|
Some modules are available in all products, and some modules are available only in some, or even just one product.
|
||||||
This section identifies and discusses modules of both types.
|
This section identifies and discusses modules of both types.
|
||||||
|
|
||||||
### Declaring Incompatibility with Module
|
### Declaring Incompatibility with Module
|
||||||
Starting in 2020.2, a plugin can declare incompatibility with an arbitrary module by specifying `<incompatible-with>` containing module ID in its `plugin.xml`.
|
Starting in 2020.2, a plugin can declare incompatibility with an arbitrary module by specifying `<incompatible-with>` containing module ID in its `plugin.xml`.
|
||||||
|
|
||||||
### Modules Available in All Products
|
### Modules Available in All Products
|
||||||
A core set of modules are available in all products based on the IntelliJ Platform.
|
A core set of modules are available in all products based on the IntelliJ Platform.
|
||||||
These modules provide a set of shared functionality.
|
These modules provide a set of shared functionality.
|
||||||
The following table lists modules that are currently available in all products.
|
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.
|
|
||||||
|
|
||||||
| Module for `<depends>` Element<br>Declaration in `plugin.xml` File | <br>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 |
|
||||||
|--------------------------------------|----------------------------------------------------------------------------------------------------------------|
|
|--------------------------------------|----------------------------------------------------------------------------------------------------------------|
|
||||||
| **`com.intellij.modules.platform`** | Messaging, UI Themes, UI Components, Files, Documents, Actions, Components, Services, Extensions, Editors |
|
| **`com.intellij.modules.platform`** | Messaging, UI Themes, UI Components, Files, Documents, Actions, Components, Services, Extensions, Editors |
|
||||||
| `com.intellij.modules.lang` | File Type, Lexer, Parser, Highlighting, References, Code Completion, Find, Rename, Formatter, Code Navigation |
|
| `com.intellij.modules.lang` | File Type, Lexer, Parser, Highlighting, References, Code Completion, Find, Rename, Formatter, Code Navigation |
|
||||||
@ -63,17 +63,17 @@ The following table lists modules that are currently available in all products.
|
|||||||
As of this writing, if a plugin: **A)** is dependent _only_ on one or more of the modules in the table above, **and B)** declares those module dependencies in `plugin.xml`, then any product developed by JetBrains based on the IntelliJ Platform will load it.
|
As of this writing, if a plugin: **A)** is dependent _only_ on one or more of the modules in the table above, **and B)** declares those module dependencies in `plugin.xml`, then any product developed by JetBrains based on the IntelliJ Platform will load it.
|
||||||
|
|
||||||
### Modules Specific to Functionality
|
### Modules Specific to Functionality
|
||||||
More specialized functionality is also delivered via modules and plugins in IntelliJ Platform-based products.
|
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.
|
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.
|
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.
|
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.
|
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 |
|
| Module or Plugin for `<depends>` Element<br>Declaration in `plugin.xml` File | <br>Functionality | IntelliJ Platform-Based<br>Product Compatibility |
|
||||||
|------------------------------------------------------------------------------|--------------------|------------------------------------------|
|
|------------------------------------------------------------------------------|--------------------|------------------------------------------|
|
||||||
| `com.intellij.modules.java` See (2) below. <br>`com.intellij.java` | **Java** language PSI Model, Inspections, Intentions, Completion, Refactoring, Test Framework | IntelliJ IDEA, Android Studio |
|
| `com.intellij.modules.java` See (2) below. <br>`com.intellij.java` | **Java** language PSI Model, Inspections, Intentions, Completion, Refactoring, Test Framework | IntelliJ IDEA, Android Studio |
|
||||||
| `com.intellij.modules.androidstudio` | Android SDK Platform, Build Tools, Platform Tools, SDK Tools | Android Studio |
|
| `com.intellij.modules.androidstudio` | Android SDK Platform, Build Tools, Platform Tools, SDK Tools | Android Studio |
|
||||||
@ -90,18 +90,18 @@ The following table lists(1) modules or built-in plugins that provide specific f
|
|||||||
| `com.jetbrains.php` | **PHP** language PSI Model, Inspections, Intentions, Completion, Refactoring, Test Framework | PhpStorm, and other products if the PHP plugin is installed. |
|
| `com.jetbrains.php` | **PHP** language PSI Model, Inspections, Intentions, Completion, Refactoring, Test Framework | PhpStorm, and other products if the PHP plugin is installed. |
|
||||||
| `JavaScript` | **JavaScript** language PSI Model, Inspections, Intentions, Completion, Refactoring, Test Framework | WebStorm, and other products if the JavaScript plugin is installed. |
|
| `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:**
|
**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.
|
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.
|
**(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.
|
||||||
This refactoring separated the Java implementation from the other, non-language portions of the platform.
|
This refactoring separated the Java implementation from the other, non-language portions of the platform.
|
||||||
Consequently, Java dependencies are expressed differently in `plugin.xml` depending on the version of the IntelliJ Platform being targeted:
|
Consequently, Java dependencies are expressed differently in `plugin.xml` depending on the version of the IntelliJ Platform being targeted:
|
||||||
* Syntax _required_ for releases prior to 2019.2, _allowable_ in all releases:
|
* Syntax _required_ for releases prior to 2019.2, _allowable_ in all releases:
|
||||||
* `plugin.xml` include `<depends>com.intellij.modules.java</depends>`
|
* `plugin.xml` include `<depends>com.intellij.modules.java</depends>`
|
||||||
* Syntax for 2019.2 and later releases:
|
* Syntax for 2019.2 and later releases:
|
||||||
* `plugin.xml` _allowable_ alternative include `<depends>com.intellij.java</depends>`
|
* `plugin.xml` _allowable_ alternative include `<depends>com.intellij.java</depends>`
|
||||||
* `build.gradle` _required_ to include `intellij { plugins 'java' }`
|
* `build.gradle` _required_ to include `intellij { plugins 'java' }`
|
||||||
|
|
||||||
## Exploring Module and Plugin APIs
|
## Exploring Module and Plugin APIs
|
||||||
Once the [dependency on a module or plugin](/basics/plugin_structure/plugin_dependencies.md) is declared in `plugin.xml`, it's useful to explore the packages and classes available in that dependency.
|
Once the [dependency on a module or plugin](/basics/plugin_structure/plugin_dependencies.md) is declared in `plugin.xml`, it's useful to explore the packages and classes available in that dependency.
|
||||||
@ -115,8 +115,8 @@ If the project is not up to date, [Reimport the Gradle project](https://www.jetb
|
|||||||
Reimporting the project will automatically update the dependencies.
|
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).
|
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).
|
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).
|
||||||
|
|
||||||
{:width="700px"}
|
{: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.
|
Drill down into the JAR files to expose the packages and (decompiled) classes.
|
||||||
|
|
||||||
### Exploring APIs as an Extender
|
### 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.
|
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.
|
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.
|
||||||
@ -138,17 +138,16 @@ Continuing the example, search the PHP plugin's `plugin.xml` file for:
|
|||||||
|
|
||||||
|
|
||||||
## Verifying Dependency
|
## Verifying Dependency
|
||||||
Before marking a plugin project as _dependent only on modules in a target product_ in addition to `com.intellij.modules.platform`, verify the plugin isn't implicitly dependent on any APIs that are specific to IntelliJ IDEA.
|
Before marking a plugin project as _dependent only on modules in a target product_ in addition to `com.intellij.modules.platform`, verify the plugin isn't implicitly dependent on any APIs that are specific to IntelliJ IDEA.
|
||||||
|
|
||||||
For [Gradle-based](/tutorials/build_system.md) projects, [Plugin Verifier](/reference_guide/api_changes_list.md#plugin-verifier) can be used to ensure compatibility with all specified target IDEs.
|
For [Gradle-based](/tutorials/build_system.md) projects, [Plugin Verifier](/reference_guide/api_changes_list.md#plugin-verifier) can be used to ensure compatibility with all specified target IDEs.
|
||||||
|
|
||||||
For [DevKit-based](/basics/getting_started/using_dev_kit.md) projects, create an SDK pointing to an installation of the intended target IntelliJ Platform-based product, e.g., PhpStorm, rather than IntelliJ IDEA.
|
For [DevKit-based](/basics/getting_started/using_dev_kit.md) projects, create an SDK pointing to an installation of the intended target IntelliJ Platform-based product, e.g., PhpStorm, rather than IntelliJ IDEA.
|
||||||
Use the same development version of the IntelliJ platform as the targeted product.
|
Use the same development version of the IntelliJ platform as the targeted product.
|
||||||
|
|
||||||
Based on the tables above, the [JetBrains Plugins Repository](https://plugins.jetbrains.com/) automatically detects the JetBrains products with which a plugin is compatible, and makes the compatibility information available to plugin authors.
|
Based on the tables above, the [JetBrains Plugins Repository](https://plugins.jetbrains.com/) automatically detects the JetBrains products with which a plugin is compatible, and makes the compatibility information available to plugin authors.
|
||||||
The compatibility information determines if plugins are available at the plugin repository to users of a particular JetBrains product.
|
The compatibility information determines if plugins are available at the plugin repository to users of a particular JetBrains product.
|
||||||
|
|
||||||
## Platform API Version Compatibility
|
## Platform API Version Compatibility
|
||||||
The API of _IntelliJ Platform_ and bundled plugins may change between releases.
|
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.
|
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.
|
||||||
|
|
||||||
|
@ -3,15 +3,13 @@ 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. -->
|
<!-- 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.
|
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)
|
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).
|
||||||
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.
|
> **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
|
### Publishing to the JetBrains Plugins Repository
|
||||||
To upload your plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com),
|
To upload your plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com), you must log in with your personal JetBrains Account.
|
||||||
you must log in with your personal JetBrains Account.
|
|
||||||
|
|
||||||
**To get your 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:**
|
**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**.
|
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.
|
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
|
### 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),
|
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.
|
||||||
please refer to the [Publishing to Custom Plugin Repositories](update_plugins_format.md) documentation.
|
|
||||||
|
@ -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. -->
|
<!-- 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.
|
See [IDE Development Instances](/basics/ide_development_instance.md) for more information about configuration and advanced settings.
|
||||||
|
|
||||||
|
@ -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.
|
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).
|
- **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
|
### Configuring IntelliJ Platform SDK
|
||||||
|
|
||||||
To set up your plugin development environment:
|
To set up your plugin development environment:
|
||||||
|
|
||||||
* Create a new *IntelliJ Platform SDK* under **File \| Project Structure**:
|
* Create a new *IntelliJ Platform SDK* under **File \| Project Structure**:
|
||||||
|

|
||||||
|
<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*.
|
||||||
|

|
||||||
|
<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/>
|
||||||
|
* In the Sourcepath tab of the SDK settings, click the *Add* button:
|
||||||
|

|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
* Specify the source code directory for the *IntelliJ IDEA Community Edition*:
|
||||||
|

|
||||||
|
<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.
|
||||||
|
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.
|
||||||
<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*.
|
|
||||||
|
|
||||||

|
|
||||||
<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/>
|
|
||||||
* In the Sourcepath tab of the SDK settings, click the *Add* button:
|
|
||||||
|
|
||||||

|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
* Specify the source code directory for the *IntelliJ IDEA Community Edition*:
|
|
||||||
|
|
||||||

|
|
||||||
<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.
|
|
||||||
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.
|
|
||||||
|
|
||||||

|

|
||||||
|
@ -3,36 +3,34 @@ 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. -->
|
<!-- 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),
|
If you intend to use a plugin repository _other than_ the [JetBrains Plugins Repository](https://plugins.jetbrains.com), you will need to:
|
||||||
you will need to:
|
* Create and maintain an `updatePlugins.xml` file on the HTTPS web server you are using for your custom repository.
|
||||||
* 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.
|
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
|
* Upload your plugin JAR/ZIP file to an HTTPS web server.
|
||||||
or a different 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).
|
* 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
|
## 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
|
Every custom plugin repository must have at least one `updatePlugins.xml` file to describe every hosted plugin's latest available version.
|
||||||
for every hosted plugin. The description in `updatePlugins.xml` is used by JetBrains IDEs to locate plugins by attributes
|
The description in `updatePlugins.xml` is used by JetBrains IDEs to locate plugins by attributes such as id, IDE version, and plugin version.
|
||||||
such as id, IDE version, and plugin version. These attributes are displayed by JetBrains IDEs to help users select or upgrade plugins.
|
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.
|
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
|
A custom plugin repository's `updatePlugins.xml` file is constructed and maintained by the repository administrator.
|
||||||
the repository. More than one `updatePlugins.xml` file may be required if consumers of the custom repository are using more
|
More than one `updatePlugins.xml` file may be required if the custom repository consumers are using more than one version of a JetBrains IDE.
|
||||||
than one version of a JetBrains IDE. For example `updatePlugins-182.xml`, `updatePlugins-183.xml` for IntelliJ IDEA 2018.2 and 2018.3 respectively.
|
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
|
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).
|
||||||
[Repository Settings/Preferences](https://www.jetbrains.com/help/idea/managing-plugins.html#repos).
|
|
||||||
|
|
||||||
### Format of updatePlugins.xml File
|
### Format of updatePlugins.xml File
|
||||||
The format of an `updatePlugins.xml` file is simply a list of sequential elements that describe each plugin:
|
The format of an `updatePlugins.xml` file is simply a list of sequential elements that describe each plugin:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!--
|
<!--
|
||||||
The <plugins> element contains the description of the plugins available at this repository. Required.
|
The <plugins> element contains the description of the plugins available at this repository. Required.
|
||||||
-->
|
-->
|
||||||
<plugins>
|
<plugins>
|
||||||
<!--
|
<!--
|
||||||
Each <plugin> element describes one plugin in the repository. Required.
|
Each <plugin> element describes one plugin in the repository. Required.
|
||||||
id - used by JetBrains IDEs to uniquely identify a plugin. Required. Must match <id> in plugin.xml
|
id - used by JetBrains IDEs to uniquely identify a plugin. Required. Must match <id> in plugin.xml
|
||||||
url - path to download the plugin JAR/ZIP file. Required. Must be HTTPS
|
url - path to download the plugin JAR/ZIP file. Required. Must be HTTPS
|
||||||
@ -53,23 +51,21 @@ The format of an `updatePlugins.xml` file is simply a list of sequential element
|
|||||||
</plugins>
|
</plugins>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:**
|
**Note:**
|
||||||
* An `updatePlugins.xml` file must contain at least one set of `<plugin></plugin>` elements.
|
* An `updatePlugins.xml` file must contain at least one set of `<plugin></plugin>` elements.
|
||||||
* A plugin `id` may be listed only once in an `updatePlugins.xml` file.
|
* A plugin `id` may be listed only once in an `updatePlugins.xml` file.
|
||||||
* Multiple plugins with the same `id` but different `idea-version` attributes must be split into separate `updatePlugins-*.xml` files.
|
* Multiple plugins with the same `id` but different `idea-version` attributes must be split into separate `updatePlugins-*.xml` files.
|
||||||
|
|
||||||
### Optional updatePlugin.xml Elements
|
### 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
|
Can additional elements be added to `updatePlugins.xml`? Yes, but it's advisable only if needed.
|
||||||
to be synchronized with each plugin's `plugin.xml` file.
|
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.
|
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
|
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.
|
||||||
[browsing the custom plugin repository](https://www.jetbrains.com/help/idea/managing-plugins.html#repos)
|
Here are the candidate elements:
|
||||||
before installation? The answer depends on the plugins and repository consumers. Here are the candidate elements:
|
|
||||||
|
|
||||||
| Element | Effects & Requirements |
|
| 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. |
|
| `<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. |
|
| `<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. |
|
| `<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. |
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ title: Using DevKit
|
|||||||
|
|
||||||
> **NOTE** For new projects, it is highly recommended to use [Gradle](/tutorials/build_system.md).
|
> **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:
|
In this section:
|
||||||
|
|
||||||
|
@ -5,26 +5,25 @@ 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. -->
|
<!-- 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 JetBrains feature for developing plugins is running or debugging a plugin project from within an IntelliJ Platform-based IDE such as IntelliJ IDEA.
|
A JetBrains feature for developing plugins is running or debugging a plugin project from within an IntelliJ Platform-based IDE such as IntelliJ IDEA.
|
||||||
Selecting the [**runIde**](/tutorials/build_system/prerequisites.md#running-a-simple-gradle-based-intellij-platform-plugin) task for a Gradle-based project (or [**Run**](getting_started/running_and_debugging_a_plugin.md) menu for a DevKit-based project) will launch a _Development Instance_ of the IDE with the plugin enabled.
|
Selecting the [**runIde**](/tutorials/build_system/prerequisites.md#running-a-simple-gradle-based-intellij-platform-plugin) task for a Gradle-based project (or [**Run**](getting_started/running_and_debugging_a_plugin.md) menu for a DevKit-based project) will launch a _Development Instance_ of the IDE with the plugin enabled.
|
||||||
This page describes how to control some of the settings for the Development Instance.
|
This page describes how to control some of the settings for the Development Instance.
|
||||||
|
|
||||||
> **TIP** Please see also [Advanced Configuration](https://www.jetbrains.com/help/idea/tuning-the-ide.html) for general VM options and properties.
|
> **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
|
## 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.
|
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.
|
The JetBrains Runtime is an environment for running IntelliJ Platform-based IDEs on Windows, macOS, and Linux.
|
||||||
It has some modifications by JetBrains, such as fixes for native crashes not present in official JDK builds.
|
It has some modifications by JetBrains, such as fixes for native crashes not present in official JDK builds.
|
||||||
A version of the JetBrains Runtime is bundled with all IntelliJ Platform-based IDEs.
|
A version of the JetBrains Runtime is bundled with all IntelliJ Platform-based IDEs.
|
||||||
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.
|
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
|
### Determining a JetBrains Runtime Version
|
||||||
The JetBrains Runtime is determined from the JDK version used to build the plugin project.
|
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.
|
||||||
If a plugin is being developed against the Java 8 SE Development Kit 8 for macOS, for example, `jdk-8u212-macosx-x64.dmg`.
|
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:
|
||||||
(This example will use macOS, but Windows and Linux follow the same procedure.)
|
|
||||||
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.
|
* 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.
|
* 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.
|
* 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.
|
* 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`.
|
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.
|
* 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
|
### 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.
|
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
|
### 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 [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.
|
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
|
## Enabling Auto-Reload
|
||||||
@ -57,28 +56,28 @@ Please note that any unloading problems in a production environment will ask the
|
|||||||
Enabled by default for target platform 2020.2 or later.
|
Enabled by default for target platform 2020.2 or later.
|
||||||
Set `autoReloadPlugins = true` in [**runIde**](/tutorials/build_system/prerequisites.md#running-a-simple-gradle-based-intellij-platform-plugin) task to enable it for earlier platform versions or `autoReloadPlugins = false` to disable it explicitly.
|
Set `autoReloadPlugins = true` in [**runIde**](/tutorials/build_system/prerequisites.md#running-a-simple-gradle-based-intellij-platform-plugin) task to enable it for earlier platform versions or `autoReloadPlugins = false` to disable it explicitly.
|
||||||
|
|
||||||
### Gradle plugin 0.4.21 and Earlier/DevKit
|
### Gradle plugin 0.4.21 and Earlier/DevKit
|
||||||
Add system property `idea.auto.reload.plugins` in the [run configuration](getting_started/running_and_debugging_a_plugin.md) (DevKit-based) or [**runIde**](/tutorials/build_system/prerequisites.md#running-a-simple-gradle-based-intellij-platform-plugin) task (Gradle-based).
|
Add system property `idea.auto.reload.plugins` in the [run configuration](getting_started/running_and_debugging_a_plugin.md) (DevKit-based) or [**runIde**](/tutorials/build_system/prerequisites.md#running-a-simple-gradle-based-intellij-platform-plugin) task (Gradle-based).
|
||||||
For [Gradle-based plugins](/tutorials/build_system/prerequisites.md) using `gradle-intellij-plugin` 0.4.17 or later, this property is set automatically.
|
For [Gradle-based plugins](/tutorials/build_system/prerequisites.md) using `gradle-intellij-plugin` 0.4.17 or later, this property is set automatically.
|
||||||
|
|
||||||
To disable auto-reload, set `idea.auto.reload.plugins` to `false` explicitly (2020.1.2+).
|
To disable auto-reload, set `idea.auto.reload.plugins` to `false` explicitly (2020.1.2+).
|
||||||
|
|
||||||
|
|
||||||
## The Development Instance Sandbox Directory
|
## The Development Instance Sandbox Directory
|
||||||
The _Sandbox Home_ directory contains the [settings, caches, logs, and plugins](#development-instance-settings-caches-logs-and-plugins) for a Development Instance of the IDE.
|
The _Sandbox Home_ directory contains the [settings, caches, logs, and plugins](#development-instance-settings-caches-logs-and-plugins) for a Development Instance of the IDE.
|
||||||
This information is stored in a different location than for the [installed IDE itself](https://intellij-support.jetbrains.com/hc/en-us/articles/206544519-Directories-used-by-the-IDE-to-store-settings-caches-plugins-and-logs).
|
This information is stored in a different location than for the [installed IDE itself](https://intellij-support.jetbrains.com/hc/en-us/articles/206544519-Directories-used-by-the-IDE-to-store-settings-caches-plugins-and-logs).
|
||||||
|
|
||||||
### Sandbox Home Location for Gradle-Based Plugin Projects
|
### Sandbox Home Location for Gradle-Based Plugin Projects
|
||||||
For Gradle-based plugins, the default Sandbox Home location is defined by the IntelliJ Platform `gradle-intellij-plugin`.
|
For Gradle-based plugins, the default Sandbox Home location is defined by the IntelliJ Platform `gradle-intellij-plugin`.
|
||||||
See [Configuring a Gradle Plugin Project](/tutorials/build_system/prerequisites.md) for more information about specifying a Sandbox Home location.
|
See [Configuring a Gradle Plugin Project](/tutorials/build_system/prerequisites.md) for more information about specifying a Sandbox Home location.
|
||||||
The default Sandbox Home location for Gradle-based plugin projects is:
|
The default Sandbox Home location for Gradle-based plugin projects is:
|
||||||
* **Windows** `<Project Dir>\build\idea-sandbox`
|
* **Windows** `<Project Dir>\build\idea-sandbox`
|
||||||
* **Linux or macOS** `<Project Dir>/build/idea-sandbox`
|
* **Linux or macOS** `<Project Dir>/build/idea-sandbox`
|
||||||
|
|
||||||
### Sandbox Home Location for DevKit-Based Plugin Projects
|
### Sandbox Home Location for DevKit-Based Plugin Projects
|
||||||
For DevKit-based plugins, the default Sandbox Home location is defined in the IntelliJ Platform Plugin SDK.
|
For DevKit-based plugins, the default Sandbox Home location is defined in the IntelliJ Platform Plugin SDK.
|
||||||
See specifying the [Sandbox Home for DevKit Projects](/basics/getting_started/setting_up_environment.md) for more information.
|
See specifying the [Sandbox Home for DevKit Projects](/basics/getting_started/setting_up_environment.md) for more information.
|
||||||
The default Sandbox Home directory location for DevKit-based plugin projects is:
|
The default Sandbox Home directory location for DevKit-based plugin projects is:
|
||||||
* **Windows:** `<User home>\.<product_system_name><product_version>\system\plugins-sandbox\`
|
* **Windows:** `<User home>\.<product_system_name><product_version>\system\plugins-sandbox\`
|
||||||
* **Linux:** `~/.<product_system_name><product_version>/system/plugins-sandbox/`
|
* **Linux:** `~/.<product_system_name><product_version>/system/plugins-sandbox/`
|
||||||
* **macOS** `~/Library/Caches/<product_system_name><product_version>/plugins-sandbox/`
|
* **macOS** `~/Library/Caches/<product_system_name><product_version>/plugins-sandbox/`
|
||||||
@ -86,9 +85,9 @@ The default Sandbox Home directory location for DevKit-based plugin projects is:
|
|||||||
### Development Instance Settings, Caches, Logs, and Plugins
|
### Development Instance Settings, Caches, Logs, and Plugins
|
||||||
Within the Sandbox Home directory are subdirectories of the Development Instance:
|
Within the Sandbox Home directory are subdirectories of the Development Instance:
|
||||||
* `config` contains settings for the IDE instance.
|
* `config` contains settings for the IDE instance.
|
||||||
* `plugins` contains folders for each plugin being run in the IDE instance.
|
* `plugins` contains folders for each plugin being run in the IDE instance.
|
||||||
* `system/caches` or `system\caches` holds the IDE instance data.
|
* `system/caches` or `system\caches` holds the IDE instance data.
|
||||||
* `system/log` or `system\log` contains the `idea.log` file for the IDE instance.
|
* `system/log` or `system\log` contains the `idea.log` file for the IDE instance.
|
||||||
|
|
||||||
Each of these Sandbox Home subdirectories can be manually cleared to reset the IDE Development Instance.
|
Each of these Sandbox Home subdirectories can be manually cleared to reset the IDE Development Instance.
|
||||||
At the next launch of a Development Instance, the subdirectories will be repopulated with the appropriate information.
|
At the next launch of a Development Instance, the subdirectories will be repopulated with the appropriate information.
|
||||||
|
@ -5,32 +5,43 @@ title: Indexing and PSI Stubs
|
|||||||
|
|
||||||
## Indices
|
## 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:
|
It supports two main types of indexes:
|
||||||
|
|
||||||
* [File-based indices](/basics/indexing_and_psi_stubs/file_based_indexes.md)
|
* [File-based indices](/basics/indexing_and_psi_stubs/file_based_indexes.md)
|
||||||
* [Stub indices](/basics/indexing_and_psi_stubs/stub_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).
|
Please see also [Improving indexing performance](/reference_guide/performance/performance.md#improving-indexing-performance).
|
||||||
|
|
||||||
## Dumb Mode
|
## 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
|
## Gists
|
||||||
|
|
||||||
Sometimes, the following conditions hold:
|
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
|
* the aggregation functionality of file-based indices is not needed.
|
||||||
* 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)
|
One just needs to calculate some data based on a particular file's contents and cache it on disk.
|
||||||
* the data can be recalculated lazily on request without major performance penalties
|
* 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.
|
||||||
|
@ -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. -->
|
<!-- 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.
|
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.
|
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.
|
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.
|
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
|
## 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:
|
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.
|
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.
|
* `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.
|
* `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.
|
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.
|
> **NOTE** Please see `com.intellij.util.indexing.DebugAssertions` on how to enable additional debugging assertions during development to assert correct index implementation.
|
||||||
|
|
||||||
@ -52,17 +57,19 @@ 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.
|
> **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.
|
* `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.
|
* `getContainingFiles()` allows collecting all files in which a particular 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.
|
* `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
|
## 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
|
### Word Index
|
||||||
|
|
||||||
Generally, the word index should be accessed indirectly by using helper methods of the [`PsiSearchHelper`](upsource:///platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java) class.
|
Generally, the word index should be accessed indirectly by using helper methods of the [`PsiSearchHelper`](upsource:///platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java) class.
|
||||||
|
|
||||||
### File Name Index
|
### File Name Index
|
||||||
|
@ -5,48 +5,69 @@ title: Stub Indexes
|
|||||||
|
|
||||||
## Stub Trees
|
## 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:
|
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)).
|
* 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)).
|
* 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 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.
|
* 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)).
|
||||||
* 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.
|
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)).
|
* 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:
|
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).
|
* 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)).
|
* 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.
|
> **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).
|
> **TIP** Please see also [Improving indexing performance](/reference_guide/performance/performance.md#improving-indexing-performance).
|
||||||
|
|
||||||
## Stub Indexes
|
## 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:
|
To access the data from an index, the following two methods are used:
|
||||||
|
|
||||||
@ -55,5 +76,4 @@ To access the data from an index, the following two methods are used:
|
|||||||
|
|
||||||
## Related Forum Discussions
|
## Related Forum Discussions
|
||||||
|
|
||||||
* [Lifecycle of stub creation](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206121959-Lifecycle-of-stub-creation/comments/206143885)
|
* [Lifecycle of stub creation](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206121959-Lifecycle-of-stub-creation/comments/206143885)
|
||||||
|
|
||||||
|
@ -7,7 +7,8 @@ If you are writing code that you would like to contribute to the IntelliJ Platfo
|
|||||||
|
|
||||||
## Following the Latest Source Code
|
## 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
|
## General Architectural Principles
|
||||||
|
|
||||||
@ -15,7 +16,9 @@ Please do your best to follow common Java architectural principles. "Effective J
|
|||||||
|
|
||||||
## Tests
|
## 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
|
## Code Formatting
|
||||||
|
|
||||||
@ -29,19 +32,25 @@ The easiest way to follow our code formatting guidelines is to reformat your cod
|
|||||||
|
|
||||||
## Inspections
|
## 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
|
## 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
|
## Commits
|
||||||
|
|
||||||
To avoid unnecessary work when reviewing your changes, please follow these guidelines:
|
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.
|
- Look through all of your changes in your patch or pull request before you submit it to us.
|
||||||
- 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.
|
Make sure that everything you've changed is there for a reason.
|
||||||
- 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 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 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 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.
|
- Please avoid moving or renaming classes unless it is necessary for the fix.
|
||||||
|
@ -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. -->
|
<!-- 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
|
## How to Use
|
||||||
Use [`PasswordSafe`](upsource:///platform/platform-api/src/com/intellij/ide/passwordSafe/PasswordSafe.kt) to work with credentials.
|
Use [`PasswordSafe`](upsource:///platform/platform-api/src/com/intellij/ide/passwordSafe/PasswordSafe.kt) to work with credentials.
|
||||||
@ -13,18 +13,18 @@ Use [`PasswordSafe`](upsource:///platform/platform-api/src/com/intellij/ide/pass
|
|||||||
```java
|
```java
|
||||||
String key = null; // e.g. serverURL, accountID
|
String key = null; // e.g. serverURL, accountID
|
||||||
CredentialAttributes credentialAttributes = createCredentialAttributes(key);
|
CredentialAttributes credentialAttributes = createCredentialAttributes(key);
|
||||||
|
|
||||||
Credentials credentials = PasswordSafe.getInstance().get(credentialAttributes);
|
Credentials credentials = PasswordSafe.getInstance().get(credentialAttributes);
|
||||||
if (credentials != null) {
|
if (credentials != null) {
|
||||||
String password = credentials.getPasswordAsString();
|
String password = credentials.getPasswordAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// or get password only
|
// or get password only
|
||||||
String password = PasswordSafe.getInstance().getPassword(credentialAttributes);
|
String password = PasswordSafe.getInstance().getPassword(credentialAttributes);
|
||||||
|
|
||||||
private CredentialAttributes createCredentialAttributes(String key) {
|
private CredentialAttributes createCredentialAttributes(String key) {
|
||||||
return new CredentialAttributes(CredentialAttributesKt.generateServiceName("MySystem", key));
|
return new CredentialAttributes(CredentialAttributesKt.generateServiceName("MySystem", key));
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Store Credentials
|
### Store Credentials
|
||||||
@ -35,10 +35,10 @@ Use [`PasswordSafe`](upsource:///platform/platform-api/src/com/intellij/ide/pass
|
|||||||
PasswordSafe.getInstance().set(credentialAttributes, credentials);
|
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
|
## Storage
|
||||||
Default storage format depends on OS.
|
The default storage format depends on the OS.
|
||||||
|
|
||||||
| OS | Storage |
|
| OS | Storage |
|
||||||
|---------|---------|
|
|---------|---------|
|
||||||
@ -46,4 +46,4 @@ Default storage format depends on OS.
|
|||||||
| macOS | Keychain using [Security Framework](https://developer.apple.com/documentation/security/keychain_services) |
|
| macOS | Keychain using [Security Framework](https://developer.apple.com/documentation/security/keychain_services) |
|
||||||
| Linux | [Secret Service API](https://specifications.freedesktop.org/secret-service/latest/) using [libsecret](https://wiki.gnome.org/Projects/Libsecret) |
|
| Linux | [Secret Service API](https://specifications.freedesktop.org/secret-service/latest/) using [libsecret](https://wiki.gnome.org/Projects/Libsecret) |
|
||||||
|
|
||||||
Users can override the default behavior in Preferences \| Appearance & Behavior \| System Settings \| Passwords.
|
Users can override the default behavior in Preferences \| Appearance & Behavior \| System Settings \| Passwords.
|
||||||
|
@ -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. -->
|
<!-- 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).
|
> **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
|
## 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.
|
Use the `PropertiesComponent.getInstance()` method for storing application-level values, and the `PropertiesComponent.getInstance(Project)` method for storing project-level values.
|
||||||
|
|
||||||
@ -24,18 +27,20 @@ To use it:
|
|||||||
- define the state class
|
- define the state class
|
||||||
- specify the storage location using `@com.intellij.openapi.components.State`
|
- 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
|
### 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
|
```java
|
||||||
@State(...)
|
@State(...)
|
||||||
class MyService implements PersistentStateComponent<MyService.State> {
|
class MyService implements PersistentStateComponent<MyService.State> {
|
||||||
|
|
||||||
static class State {
|
static class State {
|
||||||
public String value;
|
public String value;
|
||||||
}
|
}
|
||||||
@ -71,13 +76,15 @@ class MyService implements PersistentStateComponent<MyService> {
|
|||||||
|
|
||||||
### Implementing the State Class
|
### Implementing the State Class
|
||||||
|
|
||||||
The implementation of `PersistentStateComponent` works by serializing public fields, [annotated](upsource:///platform/util/src/com/intellij/util/xmlb/annotations) private fields (see also [Customizing the XML format of persisted values](#customizing-the-xml-format-of-persisted-values)), and bean properties into an XML format.
|
The implementation of `PersistentStateComponent` works by serializing public fields, [annotated](upsource:///platform/util/src/com/intellij/util/xmlb/annotations) private fields (see also [Customizing the XML format of persisted values](#customizing-the-xml-format-of-persisted-values)), and bean properties into an XML format.
|
||||||
|
|
||||||
To exclude a public field or bean property from serialization, annotate the field or getter with `@com.intellij.util.xmlb.annotations.Transient`.
|
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:
|
The following types of values can be persisted:
|
||||||
@ -119,12 +126,13 @@ class State {
|
|||||||
|
|
||||||
### Defining the Storage Location
|
### 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:
|
It has the following fields:
|
||||||
* `name` (required) — specifies the name of the state (name of the root tag in XML).
|
* `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.
|
* `storages` — one or more of `@com.intellij.openapi.components.Storage` annotations to specify the storage locations.
|
||||||
* `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.
|
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):
|
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.
|
* `@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.
|
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
|
## 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.
|
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.
|
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
|
## 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
|
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.
|
||||||
[`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
|
## 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)
|
## 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:
|
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.
|
* Module-level: module (`.iml`) file.
|
||||||
|
@ -7,42 +7,60 @@ Please make sure to read the [Code of Conduct](/CODE_OF_CONDUCT.md).
|
|||||||
|
|
||||||
## Participate in the Community
|
## Participate in the Community
|
||||||
|
|
||||||
### Participate in Newsgroups and Forums
|
### 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
|
### 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
|
### 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
|
## Help Others Learn
|
||||||
|
|
||||||
### Write Documents
|
### 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
|
### 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
|
## Contribute Code
|
||||||
|
|
||||||
### File a Bug Report
|
### 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.
|
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
|
### 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
|
### 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
|
### 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.
|
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
|
### Become a Committer
|
||||||
Developers with a long history of submitting high-quality patches can gain direct commit rights.
|
Developers with a long history of submitting high-quality patches can gain direct commit rights.
|
||||||
|
@ -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. -->
|
<!-- 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.
|
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`.
|
> **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
|
## 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_
|
For a plugin to support this, all restrictions listed below must be met.
|
||||||
inspection on all plugin descriptor files (required `plugin.xml` as well as any additional files).
|
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/)
|
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.
|
||||||
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.
|
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 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
|
### Action Group Requires ID
|
||||||
|
|
||||||
@ -26,13 +26,13 @@ All `<group>`s must declare a unique `id`.
|
|||||||
|
|
||||||
### Use Only Dynamic Extensions
|
### 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.
|
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
|
### 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
|
### 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
|
### 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
|
## Code
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ Loading/Unloading a plugin clears all cached values created using `CachedValuesM
|
|||||||
|
|
||||||
### Do not Store PSI
|
### 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
|
### 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.
|
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
|
## Troubleshooting
|
||||||
|
|
||||||
@ -80,4 +80,5 @@ To find leaks preventing clean unload, perform the following steps:
|
|||||||
- Verify that IDE runs with VM parameter `-XX:+UnlockDiagnosticVMOptions`
|
- Verify that IDE runs with VM parameter `-XX:+UnlockDiagnosticVMOptions`
|
||||||
- Open the `.hprof` snapshot generated on plugin unload, look for the plugin ID string
|
- Open the `.hprof` snapshot generated on plugin unload, look for the plugin ID string
|
||||||
- Find the `PluginClassLoader` referencing 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.
|
||||||
|
@ -3,15 +3,16 @@ title: Plugin Actions
|
|||||||
---
|
---
|
||||||
<!-- 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. -->
|
||||||
|
|
||||||
The *IntelliJ Platform* provides the concept of _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.
|
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
|
Actions are the most common way for a user to invoke the functionality of your plugin.
|
||||||
a menu or a toolbar, using a keyboard shortcut, or from the **Help \| Find Action...** lookup.
|
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.
|
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.
|
The user can customize all registered actions via [Menus and Toolbars](https://www.jetbrains.com/help/idea/customize-actions-menus-and-toolbars.html) settings.
|
||||||
|
|
||||||
Please see [Action System](/basics/action_system.md) on how to create and register actions in the IDE.
|
Please see [Action System](/basics/action_system.md) on how to create and register actions in the IDE.
|
||||||
|
@ -3,12 +3,16 @@ 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. -->
|
<!-- 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
|
### 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.
|
Some libraries use [`ServiceLoader`](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/ServiceLoader.html) to detect and load implementations.
|
||||||
For this to work in a plugin, the context class loader must be set to the plugin's classloader and restored afterwards with original one around initialization code:
|
For this to work in a plugin, the context class loader must be set to the plugin's classloader and restored afterwards with original one around initialization code:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@ -19,4 +23,4 @@ For this to work in a plugin, the context class loader must be set to the plugin
|
|||||||
} finally {
|
} finally {
|
||||||
Thread.currentThread().setContextClassLoader(current);
|
Thread.currentThread().setContextClassLoader(current);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -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. -->
|
<!-- 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
|
Plugin components are a legacy feature supported for compatibility with plugins created for older versions of the IntelliJ Platform.
|
||||||
IntelliJ Platform. Plugins using components do not support [dynamic loading](dynamic_plugins.md) (the ability to install, update, and
|
Plugins using components do not support [dynamic loading](dynamic_plugins.md) (the ability to install, update, and uninstall plugins without restarting the IDE).
|
||||||
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
|
## Migration
|
||||||
To migrate existing code from components to more modern APIs, please use the following guidelines:
|
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,
|
* To manage some state or logic that is only needed when the user performs a specific operation, use a [Service](plugin_services.md).
|
||||||
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.
|
||||||
* To store the state of your plugin at the application or project level, use a [Service](plugin_services.md),
|
See [Persisting State of Components](/basics/persisting_state_of_components.md) for details.
|
||||||
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.
|
||||||
* 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.
|
||||||
* 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.
|
||||||
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.
|
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 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)
|
* 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.
|
||||||
and place the code in the `dispose()` method. Alternatively, use `Disposer.register()` passing a `Project` or `Application` service instance
|
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)).
|
||||||
as the `parent` argument (see [Choosing a Disposable Parent](/basics/disposers.md#choosing-a-disposable-parent)).
|
|
||||||
|
@ -3,12 +3,13 @@ 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. -->
|
<!-- 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.
|
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.
|
Limited HTML elements are allowed within `<description>` and `<change-notes>` elements.
|
||||||
However, content containing HTML elements must be surrounded by `<![CDATA[ ]]>` tags.
|
However, content containing HTML elements must be surrounded by `<![CDATA[ ]]>` tags.
|
||||||
Allowed HTML elements include text formatting, paragraphs, and lists.
|
Allowed HTML elements include text formatting, paragraphs, and lists.
|
||||||
|
|
||||||
When using Gradle, a number of metadata elements will be provided at build time by [`patchPluginXml` task](/tutorials/build_system/gradle_guide.md#patching-the-plugin-configuration-file).
|
When using Gradle, a number of metadata elements will be provided at build time by [`patchPluginXml` task](/tutorials/build_system/gradle_guide.md#patching-the-plugin-configuration-file).
|
||||||
|
|
||||||
@ -16,25 +17,25 @@ When using Gradle, a number of metadata elements will be provided at build time
|
|||||||
<!-- `url` specifies the URL of the plugin homepage (can be opened from "Plugins" settings dialog) -->
|
<!-- `url` specifies the URL of the plugin homepage (can be opened from "Plugins" settings dialog) -->
|
||||||
<idea-plugin url="https://www.jetbrains.com/idea">
|
<idea-plugin url="https://www.jetbrains.com/idea">
|
||||||
|
|
||||||
<!-- Plugin name. It should be short and descriptive and in Title Case.
|
<!-- Plugin name. It should be short and descriptive and in Title Case.
|
||||||
Displayed in the "Plugins" settings dialog and the plugin repository Web interface. -->
|
Displayed in the "Plugins" settings dialog and the plugin repository Web interface. -->
|
||||||
<name>Vss Integration</name>
|
<name>Vss Integration</name>
|
||||||
|
|
||||||
<!-- Unique identifier of the plugin. Should be FQN.
|
<!-- Unique identifier of the plugin. It should be FQN.
|
||||||
Cannot be changed between the plugin versions.
|
It cannot be changed between the plugin versions.
|
||||||
If not specified, <name> will be used (not recommended). -->
|
If not specified, <name> will be used (not recommended). -->
|
||||||
<id>com.jetbrains.vssintegration</id>
|
<id>com.jetbrains.vssintegration</id>
|
||||||
|
|
||||||
<!-- Description of the plugin.
|
<!-- Description of the plugin.
|
||||||
Should be short and to the point.
|
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".
|
"integrates", "synchronizes", "adds support for" or "lets you view".
|
||||||
Don’t use marketing adjectives like “simple”, “lightweight”, or “professional”.
|
Don't use marketing adjectives like "simple", "lightweight", or "professional".
|
||||||
Don’t repeat the name of the plugin.
|
Don't repeat the name of the plugin.
|
||||||
For plugins that add language/platform/framework support, the description MUST specify
|
For plugins that add language/platform/framework support, the description MUST specify
|
||||||
the version of the corresponding language/platform/framework.
|
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.
|
Displayed in the "Plugins" settings dialog and the plugin repository Web interface.
|
||||||
Simple HTML elements can be included between <![CDATA[ ]]> tags. -->
|
Simple HTML elements can be included between <![CDATA[ ]]> tags. -->
|
||||||
<description>Integrates Volume Snapshot Service W10</description>
|
<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.
|
<!-- Mandatory dependencies on plugins or modules.
|
||||||
The FQN module names in <depends> elements are used to determine IDE compatibility for the plugin.
|
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.
|
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. -->
|
See "Compatibility with Multiple Products" and "Plugin Dependencies" for more information. -->
|
||||||
<depends>com.intellij.modules.platform</depends>
|
<depends>com.intellij.modules.platform</depends>
|
||||||
<depends>com.third.party.plugin</depends>
|
<depends>com.third.party.plugin</depends>
|
||||||
@ -75,7 +76,7 @@ When using Gradle, a number of metadata elements will be provided at build time
|
|||||||
`action.[ActionID].text|description` -->
|
`action.[ActionID].text|description` -->
|
||||||
<resource-bundle>messages.MyPluginBundle</resource-bundle>
|
<resource-bundle>messages.MyPluginBundle</resource-bundle>
|
||||||
|
|
||||||
<!-- Plugin's application components / DEPRECATED - do not use in new plugins
|
<!-- Plugin's application components / DEPRECATED - do not use in new plugins
|
||||||
See https://www.jetbrains.org/intellij/sdk/docs/basics/plugin_structure/plugin_components.html for migration steps
|
See https://www.jetbrains.org/intellij/sdk/docs/basics/plugin_structure/plugin_components.html for migration steps
|
||||||
-->
|
-->
|
||||||
<application-components>
|
<application-components>
|
||||||
@ -88,7 +89,7 @@ When using Gradle, a number of metadata elements will be provided at build time
|
|||||||
</component>
|
</component>
|
||||||
</application-components>
|
</application-components>
|
||||||
|
|
||||||
<!-- Plugin's project components / DEPRECATED - do not use in new plugins
|
<!-- Plugin's project components / DEPRECATED - do not use in new plugins
|
||||||
See https://www.jetbrains.org/intellij/sdk/docs/basics/plugin_structure/plugin_components.html for migration steps
|
See https://www.jetbrains.org/intellij/sdk/docs/basics/plugin_structure/plugin_components.html for migration steps
|
||||||
-->
|
-->
|
||||||
<project-components>
|
<project-components>
|
||||||
@ -126,7 +127,7 @@ When using Gradle, a number of metadata elements will be provided at build time
|
|||||||
|
|
||||||
<!-- Extension points defined by the plugin.
|
<!-- Extension points defined by the plugin.
|
||||||
Extension points are registered by a plugin so that other
|
Extension points are registered by a plugin so that other
|
||||||
plugins can provide this plugin with certain data.
|
plugins can provide this plugin with certain data.
|
||||||
-->
|
-->
|
||||||
<extensionPoints>
|
<extensionPoints>
|
||||||
<extensionPoint name="testExtensionPoint" beanClass="com.foo.impl.MyExtensionBean"/>
|
<extensionPoint name="testExtensionPoint" beanClass="com.foo.impl.MyExtensionBean"/>
|
||||||
@ -135,7 +136,7 @@ When using Gradle, a number of metadata elements will be provided at build time
|
|||||||
<!-- Extensions which the plugin adds to extension points
|
<!-- Extensions which the plugin adds to extension points
|
||||||
defined by the IntelliJ Platform or by other plugins.
|
defined by the IntelliJ Platform or by other plugins.
|
||||||
The "defaultExtensionNs" attribute must be set to the
|
The "defaultExtensionNs" attribute must be set to the
|
||||||
ID of the plugin defining the extension point, or to
|
ID of the plugin defining the extension point, or to
|
||||||
"com.intellij" if the extension point is defined by the
|
"com.intellij" if the extension point is defined by the
|
||||||
IntelliJ Platform. The name of the tag within the <extensions>
|
IntelliJ Platform. The name of the tag within the <extensions>
|
||||||
tag matches the name of the extension point, and the
|
tag matches the name of the extension point, and the
|
||||||
@ -144,7 +145,7 @@ When using Gradle, a number of metadata elements will be provided at build time
|
|||||||
<extensions defaultExtensionNs="VssIntegration">
|
<extensions defaultExtensionNs="VssIntegration">
|
||||||
<testExtensionPoint implementation="com.foo.impl.MyExtensionImpl"/>
|
<testExtensionPoint implementation="com.foo.impl.MyExtensionImpl"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<!-- Application-level listeners -->
|
<!-- Application-level listeners -->
|
||||||
<applicationListeners>
|
<applicationListeners>
|
||||||
<listener class="com.foo.impl.MyListener" topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/>
|
<listener class="com.foo.impl.MyListener" topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/>
|
||||||
|
@ -5,11 +5,11 @@ title: Plugin Content
|
|||||||
|
|
||||||
The plugin `jar` file must contain:
|
The plugin `jar` file must contain:
|
||||||
- the configuration file (`META-INF/plugin.xml`) ([Plugin Configuration File](plugin_configuration_file.md))
|
- the configuration file (`META-INF/plugin.xml`) ([Plugin Configuration File](plugin_configuration_file.md))
|
||||||
- the classes that implement the plugin functionality
|
- the classes that implement the plugin functionality
|
||||||
- recommended: plugin logo file(s) (`META-INF/pluginIcon*.svg`) ([Plugin Logo](plugin_icon_file.md))
|
- recommended: plugin logo file(s) (`META-INF/pluginIcon*.svg`) ([Plugin Logo](plugin_icon_file.md))
|
||||||
|
|
||||||
|
|
||||||
### Plugin Without Dependencies
|
### Plugin Without Dependencies
|
||||||
A plugin consisting of a single `.jar` file is placed in the `/plugins` directory.
|
A plugin consisting of a single `.jar` file is placed in the `/plugins` directory.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@ -26,11 +26,11 @@ A plugin consisting of a single `.jar` file is placed in the `/plugins` director
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Plugin With Dependencies
|
### Plugin With Dependencies
|
||||||
The plugin `.jar` file is placed in the `/lib` folder under the plugin's "root" folder, together with all required bundled libraries.
|
The plugin `.jar` file is placed in the `/lib` folder under the plugin's "root" folder, together with all required bundled libraries.
|
||||||
|
|
||||||
All jars from the `/lib` folder are automatically added to the classpath (see also [Plugin Class Loaders](plugin_class_loaders.md)).
|
All jars from the `/lib` folder are automatically added to the classpath (see also [Plugin Class Loaders](plugin_class_loaders.md)).
|
||||||
|
|
||||||
```text
|
```text
|
||||||
.IntelliJIDEAx0/
|
.IntelliJIDEAx0/
|
||||||
└── plugins
|
└── plugins
|
||||||
|
@ -7,13 +7,13 @@ 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.
|
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).
|
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:
|
To express dependencies on classes from other plugins or modules, perform the following three required steps:
|
||||||
|
|
||||||
## 1. Locating Plugin ID and Preparing Sandbox
|
## 1. Locating Plugin ID and Preparing Sandbox
|
||||||
For plugins published on [JetBrains Plugins Repository](https://plugins.jetbrains.com)
|
For plugins published on [JetBrains Plugins Repository](https://plugins.jetbrains.com)
|
||||||
- open plugin's detail page
|
- open plugin's detail page
|
||||||
- select _Versions_ tab
|
- select _Versions_ tab
|
||||||
- open detail page for the desired version
|
- open detail page for the desired version
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ Depending on the chosen development workflow (Gradle or DevKit), one of the two
|
|||||||
### 2.1 Gradle
|
### 2.1 Gradle
|
||||||
> **NOTE** Please see the `plugins` attribute [gradle-intellij-plugin: Configuration](https://github.com/JetBrains/gradle-intellij-plugin#configuration) for acceptable values.
|
> **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
|
```groovy
|
||||||
intellij {
|
intellij {
|
||||||
@ -41,31 +41,30 @@ When using Kotlin build script, use `setPlugins()` within the `intellij` block,
|
|||||||
intellij {
|
intellij {
|
||||||
setPlugins("org.another.plugin:1.0")
|
setPlugins("org.another.plugin:1.0")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> **NOTE** Transitive dependencies required for tests must currently be [specified explicitly](https://github.com/JetBrains/gradle-intellij-plugin/issues/38).
|
> **NOTE** Transitive dependencies required for tests must currently be [specified explicitly](https://github.com/JetBrains/gradle-intellij-plugin/issues/38).
|
||||||
|
|
||||||
### 2.2 DevKit
|
### 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.
|
> **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.
|
> **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
|
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:
|
||||||
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.
|
* 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.
|
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.
|
* 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.
|
||||||
|
|
||||||
## 3. Dependency Declaration in plugin.xml
|
## 3. Dependency Declaration in plugin.xml
|
||||||
Regardless of whether a plugin project uses [Modules Available in All Products](/basics/getting_started/plugin_compatibility.md#modules-available-in-all-products), or [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality), the correct module must be listed as a dependency in `plugin.xml`.
|
Regardless of whether a plugin project uses [Modules Available in All Products](/basics/getting_started/plugin_compatibility.md#modules-available-in-all-products), or [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality), the correct module must be listed as a dependency in `plugin.xml`.
|
||||||
If a project depends on another plugin, the dependency must be declared like a module.
|
If a project depends on another plugin, the dependency must be declared like a module.
|
||||||
If only general IntelliJ Platform features (APIs) are used, then a default dependency on `com.intellij.modules.platform` must be declared.
|
If only general IntelliJ Platform features (APIs) are used, then a default dependency on `com.intellij.modules.platform` must be declared.
|
||||||
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.
|
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
|
### 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:
|
Continuing with the example from [Section 2](#2-project-setup) above, the dependency declaration in `plugin.xml` would be:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
@ -74,11 +73,11 @@ Continuing with the example from [Section 2](#2-project-setup) above, the depend
|
|||||||
|
|
||||||
|
|
||||||
## Optional Plugin Dependencies
|
## 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
|
A project can also specify an optional plugin dependency.
|
||||||
is not installed or enabled, but part of the functionality of the plugin will not be available. In order to do that,
|
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.
|
||||||
add `optional="true" config-file="otherconfig.xml"` to the `<depends>` tag.
|
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.
|
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:
|
The main `plugin.xml` will define an annotator for Java and specify an optional dependency on the Kotlin plugin:
|
||||||
|
|
||||||
_plugin.xml_
|
_plugin.xml_
|
||||||
@ -94,7 +93,8 @@ _plugin.xml_
|
|||||||
</idea-plugin>
|
</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_
|
_withKotlin.xml_
|
||||||
|
|
||||||
|
@ -5,44 +5,47 @@ title: Plugin Extension Points
|
|||||||
|
|
||||||
> **NOTE** See [Plugin Extensions](plugin_extensions.md) for _using_ extension points in your plugin.
|
> **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:
|
There are two types of extension points:
|
||||||
|
|
||||||
* _Interface_ extension points allow other plugins to extend your plugins with _code_. When you define an interface
|
* _Interface_ extension points allow other plugins to extend your plugins with _code_.
|
||||||
extension point, you specify an interface, and other plugins will provide classes implementing that interface.
|
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.
|
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
|
* _Bean_ extension points allow other plugins to extend your plugins with _data_.
|
||||||
name of an extension class, and other plugins will provide data which will be turned into instances of that class.
|
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
|
## 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_
|
_myPlugin/META-INF/plugin.xml_
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<idea-plugin>
|
<idea-plugin>
|
||||||
<id>my.plugin</id>
|
<id>my.plugin</id>
|
||||||
|
|
||||||
<extensionPoints>
|
<extensionPoints>
|
||||||
<extensionPoint name="myExtensionPoint1"
|
<extensionPoint name="myExtensionPoint1"
|
||||||
beanClass="com.myplugin.MyBeanClass"/>
|
beanClass="com.myplugin.MyBeanClass"/>
|
||||||
|
|
||||||
<extensionPoint name="myExtensionPoint2"
|
<extensionPoint name="myExtensionPoint2"
|
||||||
interface="com.myplugin.MyInterface"/>
|
interface="com.myplugin.MyInterface"/>
|
||||||
</extensionPoints>
|
</extensionPoints>
|
||||||
|
|
||||||
</idea-plugin>
|
</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 `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 `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.
|
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.
|
The plugin that contributes to the extension point will read those properties from the `plugin.xml` file.
|
||||||
@ -55,7 +58,7 @@ _myPlugin/src/com/myplugin/MyBeanClass.java_
|
|||||||
|
|
||||||
```java
|
```java
|
||||||
public class MyBeanClass extends AbstractExtensionPointBean {
|
public class MyBeanClass extends AbstractExtensionPointBean {
|
||||||
|
|
||||||
@Attribute("key")
|
@Attribute("key")
|
||||||
public String key;
|
public String key;
|
||||||
|
|
||||||
@ -75,20 +78,20 @@ public class MyBeanClass extends AbstractExtensionPointBean {
|
|||||||
> **TIP** See [Extension properties code insight](plugin_extensions.md#extension-properties-code-insight) on how to provide smart completion/validation.
|
> **TIP** See [Extension properties code insight](plugin_extensions.md#extension-properties-code-insight) on how to provide smart completion/validation.
|
||||||
|
|
||||||
For above extension points usage in _anotherPlugin_ would look like this (see also [Declaring Extensions](plugin_extensions.md#declaring-extensions)):
|
For above extension points usage in _anotherPlugin_ would look like this (see also [Declaring Extensions](plugin_extensions.md#declaring-extensions)):
|
||||||
|
|
||||||
_anotherPlugin/META-INF/plugin.xml_
|
_anotherPlugin/META-INF/plugin.xml_
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<idea-plugin>
|
<idea-plugin>
|
||||||
<id>another.plugin</id>
|
<id>another.plugin</id>
|
||||||
|
|
||||||
<!-- declare dependency on plugin defining extension point -->
|
<!-- declare dependency on plugin defining extension point -->
|
||||||
<depends>my.plugin</depends>
|
<depends>my.plugin</depends>
|
||||||
|
|
||||||
<!-- use "my.plugin" namespace -->
|
<!-- use "my.plugin" namespace -->
|
||||||
<extensions defaultExtensionNs="my.plugin">
|
<extensions defaultExtensionNs="my.plugin">
|
||||||
<myExtensionPoint1 key="someKey"
|
<myExtensionPoint1 key="someKey"
|
||||||
implementationClass="another.some.implementation.class"/>
|
implementationClass="another.some.implementation.class"/>
|
||||||
|
|
||||||
<myExtensionPoint2 implementation="another.MyInterfaceImpl"/>
|
<myExtensionPoint2 implementation="another.MyInterfaceImpl"/>
|
||||||
</extension>
|
</extension>
|
||||||
@ -101,22 +104,22 @@ To refer to all registered extension instances at runtime, declare an [`Extensio
|
|||||||
|
|
||||||
_myPlugin/src/com/myplugin/MyExtensionUsingService.java_
|
_myPlugin/src/com/myplugin/MyExtensionUsingService.java_
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class MyExtensionUsingService {
|
public class MyExtensionUsingService {
|
||||||
|
|
||||||
private static final ExtensionPointName<MyBeanClass> EP_NAME =
|
private static final ExtensionPointName<MyBeanClass> EP_NAME =
|
||||||
ExtensionPointName.create("my.plugin.myExtensionPoint1");
|
ExtensionPointName.create("my.plugin.myExtensionPoint1");
|
||||||
|
|
||||||
public void useExtensions() {
|
public void useExtensions() {
|
||||||
for (MyBeanClass extension : EP_NAME.getExtensionList()) {
|
for (MyBeanClass extension : EP_NAME.getExtensionList()) {
|
||||||
String key = extension.getKey();
|
String key = extension.getKey();
|
||||||
String clazz = extension.getClass();
|
String clazz = extension.getClass();
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
A gutter icon for the `ExtensionPointName` declaration allows navigating to the corresponding `<extensionPoint>` declaration in `plugin.xml`.
|
A gutter icon for the `ExtensionPointName` declaration allows navigating to the corresponding `<extensionPoint>` declaration in `plugin.xml`.
|
||||||
|
|
||||||
## Dynamic Extension Points
|
## Dynamic Extension Points
|
||||||
@ -129,10 +132,11 @@ Extension points matching these conditions can then be marked as _dynamic_ by ad
|
|||||||
|
|
||||||
```xml
|
```xml
|
||||||
<extensionPoints>
|
<extensionPoints>
|
||||||
<extensionPoint name="myDynamicExtensionPoint"
|
<extensionPoint name="myDynamicExtensionPoint"
|
||||||
beanClass="com.myplugin.MyBeanClass"
|
beanClass="com.myplugin.MyBeanClass"
|
||||||
dynamic="true" />
|
dynamic="true" />
|
||||||
</extensionPoints>
|
</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".
|
||||||
|
@ -5,29 +5,29 @@ 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. -->
|
<!-- 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
|
_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.
|
||||||
that is not as straightforward as adding an action to a menu or toolbar.
|
|
||||||
|
|
||||||
The following are some of the most common tasks accomplished using extensions:
|
The following are some of the most common tasks accomplished using extensions:
|
||||||
|
|
||||||
* The `com.intellij.toolWindow` extension point allows plugins to add [tool windows](/user_interface_components/tool_windows.md)
|
* The `com.intellij.toolWindow` extension point allows plugins to add [tool windows](/user_interface_components/tool_windows.md)
|
||||||
(panels displayed at the sides of the IDE user interface);
|
(panels displayed at the sides of the IDE user interface);
|
||||||
* The `com.intellij.applicationConfigurable` and `com.intellij.projectConfigurable` extension points allow plugins to add pages to the
|
* The `com.intellij.applicationConfigurable` and `com.intellij.projectConfigurable` extension points allow plugins to add pages to the
|
||||||
[Settings/Preferences dialog](/basics/settings.md);
|
[Settings/Preferences dialog](/basics/settings.md);
|
||||||
* [Custom language plugins](/reference_guide/custom_language_support.md) use many extension points
|
* [Custom language plugins](/reference_guide/custom_language_support.md) use many extension points
|
||||||
to extend various language support features in the IDE.
|
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
|
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.
|
||||||
different parts of the IDE behavior.
|
|
||||||
|
|
||||||
## Declaring Extensions
|
## 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.
|
* `com.intellij`, if your plugin extends the IntelliJ Platform core functionality.
|
||||||
* `{ID of a plugin}`, if your plugin extends a functionality of another plugin.
|
* `{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.
|
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:
|
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 `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.
|
* 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.
|
||||||
@ -45,11 +45,11 @@ To clarify this procedure, consider the following sample section of the `plugin.
|
|||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
<!-- Declare extensions to access extension points in a custom plugin "another.plugin"
|
<!-- Declare extensions to access extension points in a custom plugin "another.plugin"
|
||||||
The "myExtensionPoint" extension point has been declared using "beanClass"
|
The "myExtensionPoint" extension point has been declared using "beanClass"
|
||||||
and exposes custom properties "key" and "implementationClass".
|
and exposes custom properties "key" and "implementationClass".
|
||||||
-->
|
-->
|
||||||
<extensions defaultExtensionNs="another.plugin">
|
<extensions defaultExtensionNs="another.plugin">
|
||||||
<myExtensionPoint key="keyValue"
|
<myExtensionPoint key="keyValue"
|
||||||
implementationClass="com.myplugin.MyExtensionPointImpl" />
|
implementationClass="com.myplugin.MyExtensionPointImpl" />
|
||||||
</extensions>
|
</extensions>
|
||||||
```
|
```
|
||||||
@ -59,7 +59,7 @@ The following properties are available always:
|
|||||||
|
|
||||||
- `id` - unique ID
|
- `id` - unique ID
|
||||||
- `order` - allows to order all defined extensions using `first`, `last` or `before|after [id]` respectively
|
- `order` - allows to order all defined extensions using `first`, `last` or `before|after [id]` respectively
|
||||||
- `os` - allows restricting extension to given OS, e.g., `os="windows"` registers the extension on Windows only
|
- `os` - allows restricting extension to given OS, e.g., `os="windows"` registers the extension on Windows only
|
||||||
|
|
||||||
|
|
||||||
### Extension Properties Code Insight
|
### Extension Properties Code Insight
|
||||||
@ -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.
|
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).
|
Attributes with `Enum` type support code insight with _lowerSnakeCased_ notation (2020.1 and later).
|
||||||
|
|
||||||
## How to get the extension points list?
|
## 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:
|
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)
|
- [`EditorExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/EditorExtensionPoints.xml)
|
||||||
- [`PlatformExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml)
|
- [`PlatformExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml)
|
||||||
- [`VcsExtensionPoints.xml`](upsource:///platform/vcs-impl/resources/META-INF/VcsExtensionPoints.xml)
|
- [`VcsExtensionPoints.xml`](upsource:///platform/vcs-impl/resources/META-INF/VcsExtensionPoints.xml)
|
||||||
|
|
||||||
|
@ -5,17 +5,17 @@ title: Plugin Logo
|
|||||||
|
|
||||||
Beginning in version 2019.1, the IntelliJ Platform supports representing a plugin with a logo.
|
Beginning in version 2019.1, the IntelliJ Platform supports representing a plugin with a logo.
|
||||||
A _Plugin Logo_ is intended to be a unique representation of a plugin's functionality, technology, or company.
|
A _Plugin Logo_ is intended to be a unique representation of a plugin's functionality, technology, or company.
|
||||||
Previously this page referred to Plugin Logos as _Plugin Icons_.
|
Previously this page referred to Plugin Logos as _Plugin Icons_.
|
||||||
|
|
||||||
**Note:** icons and images used within a plugin have different requirements.
|
**Note:** icons and images used within a plugin have different requirements.
|
||||||
See [Working with Icons and Images](/reference_guide/work_with_icons_and_images.md) for more information.
|
See [Working with Icons and Images](/reference_guide/work_with_icons_and_images.md) for more information.
|
||||||
|
|
||||||
* bullet list
|
* bullet list
|
||||||
{:toc}
|
{:toc}
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
Plugin Logos are shown in the [JetBrains Plugins Repository](https://plugins.jetbrains.com).
|
Plugin Logos are shown in the [JetBrains Plugins Repository](https://plugins.jetbrains.com).
|
||||||
They also appear in the Settings/Preferences [Plugin Manager](https://www.jetbrains.com/help/idea/managing-plugins.html) UI in IntelliJ Platform-based IDEs.
|
They also appear in the Settings/Preferences [Plugin Manager](https://www.jetbrains.com/help/idea/managing-plugins.html) UI in IntelliJ Platform-based IDEs.
|
||||||
Whether online or in the product UI, a Plugin Logo helps users to identify a plugin more quickly in a list, as shown below:
|
Whether online or in the product UI, a Plugin Logo helps users to identify a plugin more quickly in a list, as shown below:
|
||||||
|
|
||||||
{:width="800px"}
|
{:width="800px"}
|
||||||
@ -25,10 +25,10 @@ For a Plugin Logo to be displayed correctly within an IntelliJ Platform-based ID
|
|||||||
* Follow the best practices design guidelines,
|
* Follow the best practices design guidelines,
|
||||||
* Be in the correct file format,
|
* Be in the correct file format,
|
||||||
* Conform to file name conventions,
|
* Conform to file name conventions,
|
||||||
* Be in the `META-INF` folder of the plugin distribution file.
|
* Be in the `META-INF` folder of the plugin distribution file.
|
||||||
|
|
||||||
### Plugin Logo Size
|
### Plugin Logo Size
|
||||||
The Plugin Logo should be provided in one size: 40px by 40px.
|
The Plugin Logo should be provided in one size: 40px by 40px.
|
||||||
|
|
||||||
A Plugin Logo is displayed in two sizes, and scales automatically in each context:
|
A Plugin Logo is displayed in two sizes, and scales automatically in each context:
|
||||||
* 40px by 40px in the plugins list in the Plugin Manager UI.
|
* 40px by 40px in the plugins list in the Plugin Manager UI.
|
||||||
@ -37,16 +37,16 @@ A Plugin Logo is displayed in two sizes, and scales automatically in each contex
|
|||||||
Verify that Plugin Logo designs are effective in both sizes and all display contexts.
|
Verify that Plugin Logo designs are effective in both sizes and all display contexts.
|
||||||
|
|
||||||
### Plugin Logo Shape
|
### Plugin Logo Shape
|
||||||
Plugin Logo designs should leave at least 2px transparent padding around the perimeter, as shown below:
|
Plugin Logo designs should leave at least 2px transparent padding around the perimeter, as shown below:
|
||||||
|
|
||||||
{:width="225px"}
|
{:width="225px"}
|
||||||
|
|
||||||
Make sure Plugin Logos have the same visual weight as the logos in the examples below.
|
Make sure Plugin Logos have the same visual weight as the logos in the examples below.
|
||||||
The more filled a Plugin Logo design is, the less actual space it needs.
|
The more filled a Plugin Logo design is, the less actual space it needs.
|
||||||
See more examples of [visual weight compensation](https://jetbrains.design/intellij/principles/icons/#08) in the IntelliJ Platform UI Guidelines for Icons.
|
See more examples of [visual weight compensation](https://jetbrains.design/intellij/principles/icons/#08) in the IntelliJ Platform UI Guidelines for Icons.
|
||||||
|
|
||||||
For basic shapes, use the following sizes.
|
For basic shapes, use the following sizes.
|
||||||
Note the different areas of transparent padding used for each shape:
|
Note the different areas of transparent padding used for each shape:
|
||||||
|
|
||||||
| {:width="225px"} | {:width="225px"} |
|
| {:width="225px"} | {:width="225px"} |
|
||||||
|:---:|:---:|
|
|:---:|:---:|
|
||||||
@ -57,38 +57,39 @@ Note the different areas of transparent padding used for each shape:
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
### Plugin Logo Colors
|
### Plugin Logo Colors
|
||||||
If the plugin’s 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.
|
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.
|
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.
|
||||||
|
|
||||||
| {:height="200px" width="200px"} | {:height="200px" width="200px"} |
|
| {:height="200px" width="200px"} | {:height="200px" width="200px"} |
|
||||||
|:---:|:---:|
|
|:---:|:---:|
|
||||||
| _The YouTrack Plugin Logo uses<br>the YouTrack product logo_ | _The Keymap Plugin Logo uses a color<br>from the Action Colors Palette_ |
|
| _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.
|
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.
|
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 so well for a dark background.
|
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.
|
Consequently, a separate Plugin Logo for dark backgrounds is needed.
|
||||||
|
|
||||||
| {:width="225px"} | {:width="225px"} | {:width="225px"} |
|
| {:width="225px"} | {:width="225px"} | {:width="225px"} |
|
||||||
|:---:|:---:|:---:|
|
|:---:|:---:|:---:|
|
||||||
| _The light Plugin Logo design<br>works well on light UI Theme_ | _The light Plugin Logo design does<br>not work well on a dark UI Theme_ | _A separate, dark Plugin Logo design<br>works well on dark UI Theme_ |
|
| _The light Plugin Logo design<br>works well on light UI Theme_ | _The light Plugin Logo design does<br>not work well on a dark UI Theme_ | _A separate, dark Plugin Logo design<br>works well on dark UI Theme_ |
|
||||||
|
|
||||||
### Plugin Logo File Format
|
### Plugin Logo File Format
|
||||||
All Plugin Logo images must be SVG format.
|
All Plugin Logo images must be SVG format.
|
||||||
This vector image format is required because the Plugin Logo file must be small, and the image must scale without any loss of quality.
|
This vector image format is required because the Plugin Logo file must be small, and the image must scale without any loss of quality.
|
||||||
|
|
||||||
### Plugin Logo File Naming Convention
|
### Plugin Logo File Naming Convention
|
||||||
Name the Plugin Logo files according to the following conventions:
|
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.
|
* `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
|
## 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:
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
{:width="450px"}
|
{:width="450px"}
|
||||||
|
|
||||||
|
@ -7,13 +7,12 @@ title: Plugin Listeners
|
|||||||
|
|
||||||
> **NOTE** Listener implementations must be stateless and may not implement life-cycle (e.g., `Disposable`).
|
> **NOTE** Listener implementations must be stateless and may not implement life-cycle (e.g., `Disposable`).
|
||||||
|
|
||||||
_Listeners_ allow plugins to declaratively subscribe to events delivered through the message bus (see [Messaging infrastructure](/reference_guide/messaging_infrastructure.md) for details).
|
_Listeners_ allow plugins to declaratively subscribe to events delivered through the message bus (see [Messaging infrastructure](/reference_guide/messaging_infrastructure.md) for details).
|
||||||
|
|
||||||
You can define both application- and project-level listeners.
|
You can define both application- and project-level listeners.
|
||||||
|
|
||||||
Declarative registration of listeners allows you to achieve better performance compared to registering listeners
|
Declarative registration of listeners allows you to achieve better performance than registering listeners from code.
|
||||||
from code, because listener instances are created lazily (the first time an event is sent to the topic), and not
|
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.
|
||||||
during application startup or project opening.
|
|
||||||
|
|
||||||
## Defining Application-Level Listeners
|
## 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.
|
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.
|
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 `class` attribute specifies the class in your plugin that implements the listener interface and receives the events.
|
||||||
the events.
|
|
||||||
|
|
||||||
As a specific example, if you want to receive events about all changes in the virtual file system, you need
|
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 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:
|
To subscribe to this topic from code, you could use something like the following snippet:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@ -43,12 +40,12 @@ 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 use declarative registration, you no longer need to reference the `Topic` instance.
|
||||||
to the listener interface class:
|
Instead, you refer directly to the listener interface class:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<applicationListeners>
|
<applicationListeners>
|
||||||
<listener class="myPlugin.MyVfsListener"
|
<listener class="myPlugin.MyVfsListener"
|
||||||
topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/>
|
topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/>
|
||||||
</applicationListeners>
|
</applicationListeners>
|
||||||
```
|
```
|
||||||
@ -66,18 +63,17 @@ public class MyVfsListener implements BulkFileListener {
|
|||||||
|
|
||||||
## Defining Project-Level Listeners
|
## Defining Project-Level Listeners
|
||||||
|
|
||||||
Project-level listeners are registered in the same way, except that the top-level tag is
|
Project-level listeners are registered in the same way, except that the top-level tag is `<projectListeners>`.
|
||||||
`<projectListeners>`. They can be used to listen to project-level events, for example, tool window operations:
|
They can be used to listen to project-level events, for example, tool window operations:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<projectListeners>
|
<projectListeners>
|
||||||
<listener class="MyToolwindowListener"
|
<listener class="MyToolwindowListener"
|
||||||
topic="com.intellij.openapi.wm.ex.ToolWindowManagerListener" />
|
topic="com.intellij.openapi.wm.ex.ToolWindowManagerListener" />
|
||||||
</projectListeners>
|
</projectListeners>
|
||||||
```
|
```
|
||||||
|
|
||||||
The class implementing the listener interface can define a one-argument constructor accepting a `Project`,
|
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:
|
||||||
and it will receive the instance of the project for which the listener is created:
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class MyToolwindowListener implements ToolWindowManagerListener {
|
public class MyToolwindowListener implements ToolWindowManagerListener {
|
||||||
@ -92,12 +88,13 @@ public class MyToolwindowListener implements ToolWindowManagerListener {
|
|||||||
// handle the state change
|
// handle the state change
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Additional Attributes
|
## Additional Attributes
|
||||||
|
|
||||||
Registration of listeners can be restricted using the following attributes:
|
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)
|
- `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`
|
- `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.
|
||||||
|
@ -7,38 +7,39 @@ 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.
|
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 must have an implementation class that 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 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)).
|
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)).
|
||||||
|
|
||||||
#### Types
|
#### Types
|
||||||
The *IntelliJ Platform* offers three types of services: _application level_ services (global singleton), _project level_ services, and _module level_ services.
|
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).
|
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
|
#### 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.
|
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
|
## Light Services
|
||||||
|
|
||||||
> **NOTE** Light Services are available since IntelliJ Platform 2019.3.
|
> **NOTE** Light Services are available since IntelliJ Platform 2019.3.
|
||||||
|
|
||||||
A service not going to be overridden does not need to be registered in `plugin.xml` (see [Declaring a Service](#declaring-a-service)).
|
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).
|
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:
|
Restrictions:
|
||||||
|
|
||||||
* Service class must be `final`.
|
* Service class must be `final`.
|
||||||
* Constructor injection is not supported (since it is deprecated).
|
* Constructor injection is not supported (since it is deprecated).
|
||||||
* If service is a [PersistentStateComponent](/basics/persisting_state_of_components.md), roaming must be disabled (`roamingType = RoamingType.DISABLED`).
|
* If service is a [PersistentStateComponent](/basics/persisting_state_of_components.md), roaming must be disabled (`roamingType = RoamingType.DISABLED`).
|
||||||
|
|
||||||
See [Project Level Service](#project-service-sample) below for a sample.
|
See [Project Level Service](#project-service-sample) below for a sample.
|
||||||
|
|
||||||
## Declaring a Service
|
## Declaring a Service
|
||||||
|
|
||||||
@ -54,18 +55,18 @@ 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.
|
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.
|
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:
|
To clarify the service declaration procedure, consider the following fragment of the `plugin.xml` file:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<!-- Declare the application level service -->
|
<!-- Declare the application level service -->
|
||||||
<applicationService serviceInterface="mypackage.MyApplicationService"
|
<applicationService serviceInterface="mypackage.MyApplicationService"
|
||||||
serviceImplementation="mypackage.MyApplicationServiceImpl" />
|
serviceImplementation="mypackage.MyApplicationServiceImpl" />
|
||||||
|
|
||||||
<!-- Declare the project level service -->
|
<!-- Declare the project level service -->
|
||||||
<projectService serviceInterface="mypackage.MyProjectService"
|
<projectService serviceInterface="mypackage.MyProjectService"
|
||||||
serviceImplementation="mypackage.MyProjectServiceImpl" />
|
serviceImplementation="mypackage.MyProjectServiceImpl" />
|
||||||
</extensions>
|
</extensions>
|
||||||
```
|
```
|
||||||
@ -76,7 +77,8 @@ To provide custom implementation for test/headless environment, specify `testSer
|
|||||||
|
|
||||||
## Retrieving a Service
|
## 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:
|
To retrieve a service in Java code:
|
||||||
|
|
||||||
@ -99,7 +101,7 @@ This minimal sample shows [light](#light-services) `ProjectService` interacting
|
|||||||
|
|
||||||
_ProjectService.java_
|
_ProjectService.java_
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Service
|
@Service
|
||||||
public final class ProjectService {
|
public final class ProjectService {
|
||||||
|
|
||||||
@ -107,10 +109,10 @@ _ProjectService.java_
|
|||||||
|
|
||||||
public ProjectService(Project project) {
|
public ProjectService(Project project) {
|
||||||
myProject = project;
|
myProject = project;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void someServiceMethod(String parameter) {
|
public void someServiceMethod(String parameter) {
|
||||||
AnotherService anotherService = myProject.getService(AnotherService.class);
|
AnotherService anotherService = myProject.getService(AnotherService.class);
|
||||||
String result = anotherService.anotherServiceMethod(parameter, false);
|
String result = anotherService.anotherServiceMethod(parameter, false);
|
||||||
// do some more stuff
|
// do some more stuff
|
||||||
}
|
}
|
||||||
@ -119,7 +121,9 @@ _ProjectService.java_
|
|||||||
|
|
||||||
## Sample Plugin
|
## 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**
|
**To install and run the sample plugin**
|
||||||
|
|
||||||
|
@ -5,50 +5,52 @@ title: Project Structure
|
|||||||
|
|
||||||
<!--TODO split into parts accordingly to the table of contents-->
|
<!--TODO split into parts accordingly to the table of contents-->
|
||||||
|
|
||||||
This topic considers the concept of projects based on the IntelliJ Platform and related subjects, such as _modules_, _facets_, _libraries_, and _SDK_.
|
This topic considers the concept of projects based on the IntelliJ Platform and related subjects, such as _modules_, _facets_, _libraries_, and _SDK_.
|
||||||
The project structure and Java classes available to manage projects and modules are discussed.
|
The project structure and Java classes available to manage projects and modules are discussed.
|
||||||
|
|
||||||
* bullet list
|
* bullet list
|
||||||
{:toc}
|
{:toc}
|
||||||
|
|
||||||
## Project and Its Components
|
## 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.
|
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
|
### Project
|
||||||
In the IntelliJ Platform, a _project_ encapsulates all of a project's source code, libraries, and build instructions into a single organizational unit.
|
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.
|
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_.
|
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
|
### Module
|
||||||
A _module_ is a discrete unit of functionality that can be run, tested, and debugged independently.
|
A _module_ is a discrete unit of functionality that can be run, tested, and debugged independently.
|
||||||
Modules include such things as source code, build scripts, unit tests, deployment descriptors, etc.
|
Modules include such things as source code, build scripts, unit tests, deployment descriptors, etc.
|
||||||
In a project, each module can use a specific SDK or inherit the SDK defined at the project level (see the [SDK](#sdk) section below in this document).
|
In a project, each module can use a specific SDK or inherit the SDK defined at the project level (see the [SDK](#sdk) section below in this document).
|
||||||
A module can depend on other modules of the project.
|
A module can depend on other modules of the project.
|
||||||
|
|
||||||
### Library
|
### Library
|
||||||
A _library_ is an archive of compiled code (such as JAR files) on which modules depend.
|
A _library_ is an archive of compiled code (such as JAR files) on which modules depend.
|
||||||
The IntelliJ Platform supports three types of libraries:
|
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.
|
* **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`.
|
* **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.
|
* **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).
|
For more information about libraries, refer to [Library](https://www.jetbrains.com/help/idea/working-with-libraries.html).
|
||||||
|
|
||||||
### SDK
|
### 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.
|
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.
|
If a project is multi-module, the project SDK is common for all modules within the project by default.
|
||||||
Optionally, a project can configure an individual SDK for each module.
|
Optionally, a project can configure an individual SDK for each module.
|
||||||
|
|
||||||
For more information about SDKs, see [Working with SDKs](https://www.jetbrains.com/help/idea/working-with-sdks.html) in the IntelliJ IDEA Web Help.
|
For more information about SDKs, see [Working with SDKs](https://www.jetbrains.com/help/idea/working-with-sdks.html) in the IntelliJ IDEA Web Help.
|
||||||
|
|
||||||
### Facet
|
### Facet
|
||||||
A _facet_ represents a certain configuration, specific for a particular framework/technology associated with a module.
|
A _facet_ represents a certain configuration, specific for a particular framework/technology associated with a module.
|
||||||
A module can have multiple facets.
|
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.
|
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.
|
||||||
|
|
||||||
|
@ -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. -->
|
<!-- 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).
|
> **TIP** Please see also [Working with PSI efficiently](/reference_guide/performance/performance.md#working-with-psi-efficiently).
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ This page gives a list of recipes for the most common operations for working wit
|
|||||||
```java
|
```java
|
||||||
PsiJavaFile javaFile = (PsiJavaFile) psiClass.getContainingFile();
|
PsiJavaFile javaFile = (PsiJavaFile) psiClass.getContainingFile();
|
||||||
PsiPackage pkg = JavaPsiFacade.getInstance(project).findPackage(javaFile.getPackageName());
|
PsiPackage pkg = JavaPsiFacade.getInstance(project).findPackage(javaFile.getPackageName());
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
|
@ -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. -->
|
<!-- 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
|
## Architectural Overview
|
||||||
|
|
||||||
Classes used to manipulate run configurations can be split into the following groups:
|
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).
|
* [Execution](/basics/run_configurations/run_configuration_execution.md).
|
||||||
|
|
||||||
This diagram shows the main classes:
|
This diagram shows the main classes:
|
||||||
|
@ -6,47 +6,62 @@ title: Execution
|
|||||||
The standard execution of a run action goes through the following steps:
|
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 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 *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 [`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.
|
* `ProgramRunner.execute()` is called, receiving the executor and the execution environment.
|
||||||
|
|
||||||
Implementations of `ProgramRunner.execute()` go through the following steps to execute the process:
|
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.
|
* `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.
|
||||||
* `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.
|
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.
|
* The `RunContentBuilder` object is created and invoked to display the execution console in a tab of the Run or Debug tool window.
|
||||||
|
|
||||||
## Executor
|
## 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 [`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
|
## 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
|
## 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
|
* `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.
|
* `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).
|
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
|
## 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()`.
|
||||||
|
@ -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. -->
|
<!-- 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
|
* Dummy table of contents
|
||||||
{:toc}
|
{:toc}
|
||||||
|
|
||||||
## Configuration Type
|
## 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:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -20,39 +21,47 @@ Every type there is represented as an instance of [`ConfigurationType`](upsource
|
|||||||
<configurationType implementation="org.jetbrains.plugins.gradle.service.execution.GradleExternalTaskConfigurationType" />
|
<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
|
## 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`:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
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.
|
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
|
## 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:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
When implementing a run configuration, you may want to use one of the common base classes:
|
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.
|
* [`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).
|
* [`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
|
## Settings Editor
|
||||||
|
|
||||||
That common run configuration settings might be modified via:
|
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.
|
* [`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.
|
* [`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
|
## 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".
|
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.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
|
## 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
|
## 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)
|
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.
|
||||||
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).
|
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:
|
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.
|
* `setupConfigurationFromContext()` receives a blank configuration of your type and a `ConfigurationContext` containing information about a source code location (accessible by calling `getLocation()` or `getPsiLocation()`).
|
||||||
* `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.
|
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
|
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.
|
||||||
[`LocatableConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/LocatableConfigurationBase.java) as the base class.
|
|
||||||
|
|
||||||
## Running from the Gutter
|
## Running from the Gutter
|
||||||
|
|
||||||
|
@ -9,4 +9,3 @@ For more information, see:
|
|||||||
* [Settings Guide](/reference_guide/settings_guide.md) for information about Settings Extension Points and implementations.
|
* [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.
|
* [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.
|
* [Settings Tutorial](/tutorials/settings_tutorial.md) for step-by-step instructions for creating a simple set of custom Settings.
|
||||||
|
|
||||||
|
@ -3,10 +3,11 @@ 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. -->
|
<!-- 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 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:
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
* *Heavy* tests create a new project for each test.
|
* *Heavy* tests create a new project for each test.
|
||||||
* *Light* tests reuse a project from the previous test run when possible.
|
* *Light* tests reuse a project from the previous test run when possible.
|
||||||
|
|
||||||
@ -23,13 +24,14 @@ 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.
|
> **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`).
|
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`).
|
||||||
|
|
||||||
|
|
||||||
## Heavy Tests
|
## Heavy Tests
|
||||||
|
|
||||||
> **NOTE** If you need to set up a multi-module project for your tests, you **must** write a heavy test.
|
> **NOTE** If you need to set up a multi-module project for your tests, you **must** write a heavy test.
|
||||||
|
|
||||||
> **NOTE** In 2019.3, `PlatformTestCase` has been renamed to `HeavyPlatformTestCase` reflecting its "heavy test" characteristics.
|
> **NOTE** In 2019.3, `PlatformTestCase` has been renamed to `HeavyPlatformTestCase` reflecting its "heavy test" characteristics.
|
||||||
|
|
||||||
|
@ -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. -->
|
<!-- 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.
|
[`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.
|
> **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).
|
> 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.
|
> **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.
|
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
|
### 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:
|
You can use one of the following markers:
|
||||||
* `<caret>` specifies the position where the caret should be placed.
|
* `<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.
|
* `<selection>` and `</selection>` specify the start and end of the selected text range.
|
||||||
* `<block>` and `</block>` specify the start and end points of the column selection.
|
* `<block>` and `</block>` specify the column selection's start and end points.
|
||||||
|
@ -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. -->
|
<!-- 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
|
```xml
|
||||||
<warning descr="expected error message">code to be highlighted</warning>
|
<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>`
|
* `<error>`
|
||||||
* `<warning>`
|
* `<warning>`
|
||||||
@ -40,7 +47,7 @@ The tag can also have the following optional attributes:
|
|||||||
* `effectType` expected effect type for the highlighting (see [`EffectType`](upsource:///platform/core-api/src/com/intellij/openapi/editor/markup/EffectType.java))
|
* `effectType` expected effect type for the highlighting (see [`EffectType`](upsource:///platform/core-api/src/com/intellij/openapi/editor/markup/EffectType.java))
|
||||||
* `fontType` expected font style for the highlighting (0 - normal, 1 - bold, 2 - italic, 3 - bold italic)
|
* `fontType` expected font style for the highlighting (0 - normal, 1 - bold, 2 - italic, 3 - bold italic)
|
||||||
|
|
||||||
> **NOTE** *Nested* tags are **supported**:
|
> **NOTE** *Nested* tags are **supported**:
|
||||||
> ```<warning>warning_highlight<info>warning_and_info_highlight</info>warning_highlight</warning>```
|
> ```<warning>warning_highlight<info>warning_and_info_highlight</info>warning_highlight</warning>```
|
||||||
> *Overlapping* tags (annotations) are currently **not supported** in the test framework (but display correctly in the editor, albeit this is not an officially supported scenario):
|
> *Overlapping* tags (annotations) are currently **not supported** in the test framework (but display correctly in the editor, albeit this is not an officially supported scenario):
|
||||||
> ```<warning>warning_highlight<info>warning-and_info_highlight</warning>info_highlight</info>```
|
> ```<warning>warning_highlight<info>warning-and_info_highlight</warning>info_highlight</info>```
|
||||||
|
@ -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. -->
|
<!-- 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 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.
|
* 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:
|
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 recommended approach to mocking.
|
||||||
* 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 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
|
## Topics
|
||||||
* [Tests and Fixtures](tests_and_fixtures.md)
|
* [Tests and Fixtures](tests_and_fixtures.md)
|
||||||
|
@ -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. -->
|
<!-- 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.
|
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.
|
||||||
|
|
||||||
|
@ -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:
|
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.
|
* `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.
|
* `performEditorAction()` simulates the execution of an action in the in-memory editor context.
|
||||||
* `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).
|
* `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.
|
* `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.
|
* `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()`.
|
||||||
|
@ -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. -->
|
<!-- 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:
|
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
|
||||||
|
|
||||||
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
|
* Specific code insight
|
||||||
* Direct access to framework-specific functionality
|
* Direct access to framework-specific functionality
|
||||||
@ -53,7 +55,7 @@ Refer to the [Struts 2 plugin](https://github.com/JetBrains/intellij-plugins/tre
|
|||||||
|
|
||||||
Tool integration makes it possible to manipulate third-party tools and components directly from the IDE without switching contexts, that implies:
|
Tool integration makes it possible to manipulate third-party tools and components directly from the IDE without switching contexts, that implies:
|
||||||
|
|
||||||
* Implementation of additional actions
|
* Implementation of additional actions
|
||||||
* Related UI components
|
* Related UI components
|
||||||
* Access to external resources
|
* Access to external resources
|
||||||
|
|
||||||
@ -61,4 +63,6 @@ Refer to the [Gerrit integration](https://plugins.jetbrains.com/plugin/7272?pr=i
|
|||||||
|
|
||||||
## User Interface Add-Ons
|
## 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.
|
||||||
|
@ -8,63 +8,88 @@ The virtual file system (VFS) is a component of the *IntelliJ Platform* that enc
|
|||||||
It serves the following main purposes:
|
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.)
|
* 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.
|
* 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.
|
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.
|
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.
|
> **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.
|
> 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
|
## 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.
|
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)
|
* [`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)
|
* [`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
|
## 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.
|
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.
|
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.
|
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.
|
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.
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
## Working with PlantUML
|
## Working with PlantUML
|
||||||
These are temporary instructions, pending a move of more [diagrams and utilities](https://github.com/JetBrains/intellij-community/tree/master/platform/docs) from the IntelliJ Platform codebase.
|
These are temporary instructions, pending a move of more [diagrams and utilities](https://github.com/JetBrains/intellij-community/tree/master/platform/docs) from the IntelliJ Platform codebase.
|
||||||
|
|
||||||
* If you are unfamiliar with PlantUML, review the [quick start](https://plantuml.com/starting) instructions.
|
* If you are unfamiliar with PlantUML, review the [quick start](https://plantuml.com/starting) instructions.
|
||||||
* Install [Graphviz](https://plantuml.com/graphviz-dot) on your machine.
|
* Install [Graphviz](https://plantuml.com/graphviz-dot) on your machine.
|
||||||
* Get and install the [PlantUML Integration plugin](https://plugins.jetbrains.com/plugin/7017-plantuml-integration) for IntelliJ IDEA:
|
* Get and install the [PlantUML Integration plugin](https://plugins.jetbrains.com/plugin/7017-plantuml-integration) for IntelliJ IDEA:
|
||||||
* Set the `GRAPHVIZ_DOT` system or environment property to point to the directory containing the Graphviz executable on your machine.
|
* Set the `GRAPHVIZ_DOT` system or environment property to point to the directory containing the Graphviz executable on your machine.
|
||||||
For example, `export GRAPHVIZ_DOT="/usr/local/Cellar/graphviz/2.42.3/bin/dot"`
|
For example, `export GRAPHVIZ_DOT="/usr/local/Cellar/graphviz/2.42.3/bin/dot"`
|
||||||
* In the PlantUML plugin Settings (**Preferences/Settings \| Other Settings \| PlantUML**) set:
|
* In the PlantUML plugin Settings (**Preferences/Settings \| Other Settings \| PlantUML**) set:
|
||||||
* The "Additional 'plantuml.include.path'" to be the absolute path to the directory containing the `jb-plantuml-theme.puml` file on your machine.
|
* The "Additional 'plantuml.include.path'" to be the absolute path to the directory containing the `jb-plantuml-theme.puml` file on your machine.
|
||||||
For example, `/<path to sdk root>/buildUML` or, if you have the IntelliJ-Community source code, `/<path to intellij-community root>/platform/docs/`.
|
For example, `/<path to sdk root>/buildUML` or, if you have the IntelliJ-Community source code, `/<path to intellij-community root>/platform/docs/`.
|
||||||
* The "PlantUML config" to `!include jb-plantuml-theme.puml`
|
* The "PlantUML config" to `!include jb-plantuml-theme.puml`
|
||||||
|
|
||||||
When a *.puml file is open in the IDE editor, the PlantUML Integration plugin will show a preview.
|
When a *.puml file is open in the IDE editor, the PlantUML Integration plugin will show a preview.
|
||||||
To save a diagram in SVG format, change the file extension from the default PNG to SVG when saving the diagram from the preview window.
|
To save a diagram in SVG format, change the file extension from the default PNG to SVG when saving the diagram from the preview window.
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
## 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.
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
[][gh:build]
|
[][gh:build]
|
||||||
[][jb:slack]
|
[][jb:slack]
|
||||||
|
|
||||||
Learn how to build plugins using IntelliJ Platform SDK for the [JetBrains products][jb:products] by experimenting with
|
Learn how to build plugins using IntelliJ Platform SDK for the [JetBrains products][jb:products] by experimenting with our code samples.
|
||||||
our code samples. These samples show you how features work and help you jumpstart your plugins.
|
These samples show you how features work and help you jumpstart your plugins.
|
||||||
|
|
||||||
There is also [IntelliJ Platform Plugin Template][gh:template] project available.
|
There is also [IntelliJ Platform Plugin Template][gh:template] project available.
|
||||||
|
|
||||||
@ -20,15 +20,13 @@ 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.
|
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
|
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].
|
||||||
to the [Plugin Configuration File documentation][docs:plugin.xml]. It describes definitions of the actions, extensions,
|
It describes definitions of the actions, extensions, or listeners provided by the plugin.
|
||||||
or listeners provided by the plugin.
|
|
||||||
|
|
||||||
## Code Samples
|
## Code Samples
|
||||||
|
|
||||||
In the following table, you may find all available samples provided in the separated directories as stand-alone
|
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.
|
||||||
projects available for running with the Gradle `:runIde` task.
|
|
||||||
|
|
||||||
| Code Sample | Description |
|
| Code Sample | Description |
|
||||||
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| [Action Basics](./action_basics) | Action and Action Group patterns implementation, adds entries to the Tools menu. |
|
| [Action Basics](./action_basics) | Action and Action Group patterns implementation, adds entries to the Tools menu. |
|
||||||
|
@ -24,4 +24,3 @@ includeBuild '../settings'
|
|||||||
includeBuild '../simple_language_plugin'
|
includeBuild '../simple_language_plugin'
|
||||||
includeBuild '../tool_window'
|
includeBuild '../tool_window'
|
||||||
includeBuild '../tree_structure_provider'
|
includeBuild '../tree_structure_provider'
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ This Plugin registers the [`PopupDialogAction`][file:PopupDialogAction] action,
|
|||||||
|
|
||||||
Additional features of the plugin:
|
Additional features of the plugin:
|
||||||
- [Using the `<override-text>`][docs:action-override] element in an `<action>` element is demonstrated in the `plugin.xml` declaration to add the `PopupDialogAction` action directly to the `ToolsMenu`.
|
- [Using the `<override-text>`][docs:action-override] element in an `<action>` element is demonstrated in the `plugin.xml` declaration to add the `PopupDialogAction` action directly to the `ToolsMenu`.
|
||||||
- [Localization of action and group][docs:action-locale] `text` and `description` attributes using a `<resource-bundle>` is demonstrated in the declaration to add a new group to the `EditorPopupMenu`.
|
- [Localization of action and group][docs:action-locale] `text` and `description` attributes using a `<resource-bundle>` is demonstrated in the declaration to add a new group to the `EditorPopupMenu`.
|
||||||
|
|
||||||
### Actions
|
### Actions
|
||||||
|
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'comparing_references_inspection'
|
||||||
|
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'conditional_operator_intention'
|
||||||
|
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'editor'
|
||||||
|
|
||||||
|
@ -28,4 +28,3 @@ patchPluginXml {
|
|||||||
sinceBuild = '202'
|
sinceBuild = '202'
|
||||||
untilBuild = '202.*'
|
untilBuild = '202.*'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'facet'
|
||||||
|
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'framework'
|
||||||
|
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'inspection'
|
||||||
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
# 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.
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'kotlin'
|
||||||
|
|
||||||
|
@ -27,4 +27,4 @@ patchPluginXml {
|
|||||||
version = project.version
|
version = project.version
|
||||||
sinceBuild = '202'
|
sinceBuild = '202'
|
||||||
untilBuild = '202.*'
|
untilBuild = '202.*'
|
||||||
}
|
}
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'live_templates'
|
||||||
|
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'maxOpenProjects'
|
||||||
|
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'module'
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
## Product Specific Code Samples
|
## Product Specific Code Samples
|
||||||
|
|
||||||
Please note, all samples in this folder must be imported into Gradle explicitly as they're not included in the default Gradle composite build.
|
Please note, all samples in this folder must be imported into Gradle explicitly as they're not included in the default Gradle composite build.
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'pycharm'
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
## Quickstart
|
## 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,
|
- fetch libraries used in the project,
|
||||||
- retrieve the information about the module details,
|
- retrieve the information about the module details,
|
||||||
- rename the used SDK,
|
- rename the used SDK,
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'project_model'
|
||||||
|
|
||||||
|
@ -27,4 +27,4 @@ patchPluginXml {
|
|||||||
version = project.version
|
version = project.version
|
||||||
sinceBuild = '202'
|
sinceBuild = '202'
|
||||||
untilBuild = '202.*'
|
untilBuild = '202.*'
|
||||||
}
|
}
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'project_view_pane'
|
||||||
|
|
||||||
|
@ -27,4 +27,4 @@ patchPluginXml {
|
|||||||
version = project.version
|
version = project.version
|
||||||
sinceBuild = '202'
|
sinceBuild = '202'
|
||||||
untilBuild = '202.*'
|
untilBuild = '202.*'
|
||||||
}
|
}
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'projectWizard'
|
||||||
|
|
||||||
|
@ -34,4 +34,3 @@ public class DemoSettingsEditor extends SettingsEditor<DemoRunConfiguration> {
|
|||||||
myScriptName.setComponent(new TextFieldWithBrowseButton());
|
myScriptName.setComponent(new TextFieldWithBrowseButton());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,2 +1 @@
|
|||||||
rootProject.name = 'settings'
|
rootProject.name = 'settings'
|
||||||
|
|
||||||
|
@ -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.
|
// 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'
|
rootProject.name = 'simple_language_plugin'
|
||||||
|
|
||||||
|
@ -196,4 +196,4 @@
|
|||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
</attributes>
|
</attributes>
|
||||||
</scheme>
|
</scheme>
|
||||||
|
@ -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. -->
|
<!-- 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)
|
#### [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)
|
#### [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)
|
#### [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)
|
#### [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
|
#### 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)
|
#### [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)
|
#### [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)
|
#### [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
|
#### Part IX - Custom IDEs
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ title: Getting Help
|
|||||||
|
|
||||||
## Problems with the Guide
|
## Problems with the Guide
|
||||||
|
|
||||||
If you’re 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’re 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 it’s for a discussion, ideas on improvements or suggestions.
|
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 it’s 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:
|
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
|
* [#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.
|
Of course, all issues will be used to try and improve this guide.
|
||||||
|
@ -3,44 +3,60 @@ 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. -->
|
<!-- 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.
|
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
|
## 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
|
## 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.
|
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.
|
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
|
### IDEs Based on the IntelliJ Platform
|
||||||
The IntelliJ Platform underlies many JetBrains IDEs.
|
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.
|
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.
|
> **TIP** Qualifying Open Source projects can [apply for free licenses](https://www.jetbrains.com/community/opensource/) of JetBrains products.
|
||||||
|
|
||||||
The following IDEs are based on the IntelliJ Platform:
|
The following IDEs are based on the IntelliJ Platform:
|
||||||
@ -54,15 +70,22 @@ The following IDEs are based on the IntelliJ Platform:
|
|||||||
* [PhpStorm](https://www.jetbrains.com/phpstorm/)
|
* [PhpStorm](https://www.jetbrains.com/phpstorm/)
|
||||||
* [PyCharm](https://www.jetbrains.com/pycharm/)
|
* [PyCharm](https://www.jetbrains.com/pycharm/)
|
||||||
* [Rider](#rider)
|
* [Rider](#rider)
|
||||||
* [RubyMine](https://www.jetbrains.com/ruby/)
|
* [RubyMine](https://www.jetbrains.com/ruby/)
|
||||||
* [WebStorm](https://www.jetbrains.com/webstorm/)
|
* [WebStorm](https://www.jetbrains.com/webstorm/)
|
||||||
* [Android Studio](https://developer.android.com/studio/index.html) IDE from Google.
|
* [Android Studio](https://developer.android.com/studio/index.html) IDE from Google.
|
||||||
* [Comma](https://commaide.com/) IDE for Raku (formerly known as Perl 6)
|
* [Comma](https://commaide.com/) IDE for Raku (formerly known as Perl 6)
|
||||||
* [CUBA Studio](https://www.cuba-platform.com/)
|
* [CUBA Studio](https://www.cuba-platform.com/)
|
||||||
|
|
||||||
#### Rider
|
#### 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.
|
||||||
|
@ -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. -->
|
<!-- 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
|
## Essential Concepts
|
||||||
|
|
||||||
- [Creating Your First Plugin](/basics/getting_started.md).
|
- [Creating Your First Plugin](/basics/getting_started.md).
|
||||||
- [Testing plugins](/basics/testing_plugins/testing_plugins.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.
|
- [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
|
## 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
|
## 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
|
* [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.
|
* [Code inspections](/tutorials/code_inspections.md) - code analysis that looks at the syntax trees and semantic models and highlight issues in the editor.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user