diff --git a/.gitignore b/.gitignore index 09333365b..7e1e93883 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,3 @@ gradle-app.setting # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) !gradle-wrapper.jar - diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 1009fb520..7bc55889e 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -5,5 +5,5 @@ title: Code of Conduct ## Code of Conduct -This project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct). Please make sure you read it. - +This project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct). +Please make sure you read it. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0e00727ef..f7ee8a14f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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. * Dummy list item {:toc} - + ## Setting Up the Documentation Build Environment -This site runs via [Jekyll](https://jekyllrb.com), which is a popular static site generator, written in Ruby. It can be hosted locally to ensure that any changes are correct. Once set up, running the site is as easy as calling `rake preview`. +This site runs via [Jekyll](https://jekyllrb.com), which is a popular static site generator, written in Ruby. +It can be hosted locally to ensure that any changes are correct. +Once set up, running the site is as easy as calling `rake preview`. -Alternatively, the site can also be hosted in a [Docker container](https://www.docker.com). On Mac and Windows, this means the site is hosted in a virtual machine. Docker maintains this container, building it based on the instructions in the [`Dockerfile`](Dockerfile). All dependencies (Ruby, etc.) are automatically installed when building the image, which reduces the manual configuration steps. The Docker image is also used to build the [published site](https://www.jetbrains.org/intellij/sdk/docs/index.html), so it is a known working environment. +Alternatively, the site can also be hosted in a [Docker container](https://www.docker.com). +On Mac and Windows, this means the site is hosted in a virtual machine. +Docker maintains this container, building it based on the instructions in the [`Dockerfile`](Dockerfile). +All dependencies (Ruby, etc.) are automatically installed when building the image, which reduces the manual configuration steps. +The Docker image is also used to build the [published site](https://www.jetbrains.org/intellij/sdk/docs/index.html), so it is a known working environment. ### Developing Documentation with Docker @@ -31,18 +37,25 @@ Follow these steps to work with Docker: * Start the Docker container called `intellij-sdk-docs`. * Forward port 4000 from the Docker container to port 4000 on the Docker client. - > **NOTE** For Windows and Mac, this means port 4000 of the Docker container is forwarded to port 4000 of the Docker virtual machine, not `localhost`. For Linux, the Docker client is the host machine, so `localhost:4000` is forwarded to port 4000 on the Docker container. + > **NOTE** For Windows and Mac, this means port 4000 of the Docker container is forwarded to port 4000 of the Docker virtual machine, not `localhost`. + > For Linux, the Docker client is the host machine, so `localhost:4000` is forwarded to port 4000 on the Docker container. > - > To hit the container's port 4000 from Windows or the Mac, it is necessary to hit the IP address of the Docker client (virtual machine). Use `docker-machine ip default` to get the IP address of the Docker client. Use `X.X.X.X:4000` to hit the client in the virtual machine, which is mapped to the container's port 4000. + > To hit the container's port 4000 from Windows or the Mac, it is necessary to hit the IP address of the Docker client (virtual machine). + > Use `docker-machine ip default` to get the IP address of the Docker client. + > Use `X.X.X.X:4000` to hit the client in the virtual machine, which is mapped to the container's port 4000. > - > Alternatively, modify the virtual machine's settings to forward port 4000 automatically to `localhost`. See this [blog post](https://acaird.github.io/computers/2014/11/16/docker-virtualbox-host-networking) for more details. - - * 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`. + > 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. - > **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: - * `rake bootstrap`, which ensures all of the prerequisites are installed, + > **NOTE** If running on Windows in an MSYS bash script (e.g., the "Docker Quickstart Terminal"), the path to the local folder needs to be properly escaped, or the MSYS environment will translate the paths to standard Windows path, and causing an error such as `invalid value "C:\\Users\\...;C:\\Program Files\\Git\\usr\\src\\app" for flag -v`. + > To fix this problem, prefix the full path with double slashes, e.g., `-v //c/Users/...`, or `docker run -p 4000:4000 -v /$PWD:/usr/src/app intellij-sdk-docs` (note the leading slash before `$PWD`). + + * Run the commands in the Dockerfile's `CMD` instruction to execute: + * `rake bootstrap`, which ensures all of the prerequisites are installed, * `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). @@ -52,11 +65,13 @@ To build the documentation site, you need: * Ruby 2 - Jekyll is a Ruby application. * Ruby 2 DevKit (for Windows) - Some of Jekyll's dependencies need to be compiled, and require the DevKit to be installed. -* `gem install bundler` - the site uses [Bundler](https://bundler.io) to manage gem dependencies within the repository, rather than globally installing to the local operating system. Run this command to install the Bundler toolset globally. +* `gem install bundler` - the site uses [Bundler](https://bundler.io) to manage gem dependencies within the repository, rather than globally installing to the local operating system. + Run this command to install the Bundler toolset globally. #### macOS -macOS comes with Ruby already installed. The only steps required are: +macOS comes with Ruby already installed. +The only steps required are: * `gem install bundler` @@ -73,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` * Add the line `- C:\tools\ruby21` (including the leading minus sign) -> **NOTE** Before running the `rake bootstrap` step listed below, please run the `devkitvars.bat` file from the DevKit. E.g. `C:\tools\DevKit\devkitvars.bat` +> **NOTE** Before running the `rake bootstrap` step listed below, please run the `devkitvars.bat` file from the DevKit. +> E.g. `C:\tools\DevKit\devkitvars.bat` ### Bootstrapping the Documentation Build Environment 1. Ensure Bundler is installed - `gem install bundler`. 2. On Windows, ensure the `devkitvars.bat` file has been run in the current command prompt (e.g., `c:\tools\DevKit\devkitvars.bat`). 3. Clone the documentation site. -4. Initialize and update the `sdkdocs-template` submodule - `git submodule init` and `git submodule update` +4. Initialize and update the `sdkdocs-template` submodule - `git submodule init` and `git submodule update`. 5. `rake bootstrap` - this uses Bundler to download all required gems. -6. `rake preview` - this will build the site, and host it in a local webserver. +6. `rake preview` - this will build the site, and host it in a local webserver. ### Building and Previewing the Site -To build and test the site, run `rake preview`. This will build the site and host it using the config provided. The URL of the hosted website is displayed on the screen and depends on the `baseurl` field defined in `_config.yml`. +To build and test the site, run `rake preview`. +This will build the site and host it using the config provided. +The URL of the hosted website is displayed on the screen and depends on the `baseurl` field defined in `_config.yml`. > **NOTE** You must use `localhost` as hostname, _NOT_ 0.0.0.0, otherwise fonts fail to load. ## 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` 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 `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 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. After cloning, a submodule needs to be initialized and updated: @@ -103,14 +121,14 @@ git submodule init 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. -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. +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. 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. 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. 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: -* [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. 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. Always test code changes by building and testing the SDK code sample. - diff --git a/README.md b/README.md index 29eaaba26..4ae09cbaa 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ 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 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). diff --git a/_SUMMARY.md b/_SUMMARY.md index 6053bae7b..fe8ed71b9 100644 --- a/_SUMMARY.md +++ b/_SUMMARY.md @@ -44,7 +44,7 @@ * [Plugin Configuration File](basics/plugin_structure/plugin_configuration_file.md) * [Plugin Logo (Icon)](basics/plugin_structure/plugin_icon_file.md) * [Plugin Dependencies](basics/plugin_structure/plugin_dependencies.md) -* [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) * [Kotlin for Plugin Developers](tutorials/kotlin.md) * [Internal Actions Menu](reference_guide/internal_actions/internal_actions_intro.md) diff --git a/appendix/glossary.md b/appendix/glossary.md index 09e23a974..4d34796d4 100644 --- a/appendix/glossary.md +++ b/appendix/glossary.md @@ -6,7 +6,7 @@ title: Glossary ## A 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_ 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). ## J - + 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. @@ -77,13 +77,13 @@ Stubs ## V 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)_ : A [Virtual File](/basics/architectural_overview/virtual_file.md) represents a file in a → _Virtual File System_. 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 diff --git a/appendix/plugin_repository_obsolete.md b/appendix/plugin_repository_obsolete.md index 5f750245a..ad1ade683 100644 --- a/appendix/plugin_repository_obsolete.md +++ b/appendix/plugin_repository_obsolete.md @@ -15,10 +15,9 @@ redirect_from: --- -JetBrains provides an official plugins repository [JetBrains Plugin Repository](https://plugins.jetbrains.com) for all IntelliJ Platform-based IDEs, -as well as TeamCity (limited functionality). - -> **WARNING** **Part X - Plugin Repository** pages have moved to [JetBrains Marketplace](https://plugins.jetbrains.com/docs/marketplace/about-marketplace.html) documentation, please update your bookmarks. +JetBrains provides an official plugins repository [JetBrains Plugin Repository](https://plugins.jetbrains.com) for all IntelliJ Platform-based IDEs, as well as TeamCity (limited functionality). + +> **WARNING** **Part X - Plugin Repository** pages have moved to [JetBrains Marketplace](https://plugins.jetbrains.com/docs/marketplace/about-marketplace.html) documentation, please update your bookmarks. 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 Recommendations](https://plugins.jetbrains.com/docs/marketplace/intellij-plugin-recommendations.html) * [Custom Release Channels](https://plugins.jetbrains.com/docs/marketplace/custom-release-channels.html) - diff --git a/appendix/resources/consulting.md b/appendix/resources/consulting.md index 4aa021c1d..2c87bd4a6 100644 --- a/appendix/resources/consulting.md +++ b/appendix/resources/consulting.md @@ -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) | -/- | | Daniel Espendiller | daniel@espendiller.net | -/- | | 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/). -| Alexander Schwartz | [msg.group](https://msg.group/), alexander.schwartz@msg.group | Custom Language support around documentation-as-code, especially AsciiDoc and Antora. Plugin: [AsciiDoc](https://plugins.jetbrains.com/plugin/7391-asciidoc) -| Alexey Stukalov | info@cuba-platform.com, [www.haulmont.com](https://www.haulmont.com/services/cuba-platform-services/support/) | Plugins: [CUBA](https://plugins.jetbrains.com/plugin/7249-cuba). +| 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/), alexander.schwartz@msg.group | Custom Language support around documentation-as-code, especially AsciiDoc and Antora. Plugin: [AsciiDoc](https://plugins.jetbrains.com/plugin/7391-asciidoc) +| Alexey Stukalov | info@cuba-platform.com, [www.haulmont.com](https://www.haulmont.com/services/cuba-platform-services/support/) | Plugins: [CUBA](https://plugins.jetbrains.com/plugin/7249-cuba). | Edument | jonathan@edument.cz, [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. diff --git a/appendix/resources/useful_links.md b/appendix/resources/useful_links.md index 3011bc5c9..1cc2ab85c 100644 --- a/appendix/resources/useful_links.md +++ b/appendix/resources/useful_links.md @@ -24,7 +24,7 @@ The following links represent useful resources for working with the _IntelliJ Pl * [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) * [Indices Viewer](https://plugins.jetbrains.com/plugin/13029-indices-viewer/) - + ### 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 * [Building IntelliJ IDEA plugins in Scala](https://www.youtube.com/watch?v=IPO-cY_giNA) Igal Tabachnik, 2020 diff --git a/basics/action_system.md b/basics/action_system.md index 1cce9d055..1c06fde86 100644 --- a/basics/action_system.md +++ b/basics/action_system.md @@ -4,11 +4,11 @@ title: Action System ## Introduction -The actions system is an extension point that allows plugins to add their items to IntelliJ Platform-based IDE menus and toolbars. -For example, one of the action classes is responsible for the **File \| Open File...** menu item and for the **Open File** toolbar button. +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 the **Open File** toolbar button. -Actions in the IntelliJ Platform require a [code implementation](#action-implementation) and must be [registered](#registering-actions) with the IntelliJ Platform. -The action implementation determines the contexts in which an action is available, and its functionality when selected in the UI. +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. 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. @@ -21,43 +21,43 @@ The rest of this page is an overview of actions as an extension point. ## 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). -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 -exists for the entire lifetime of the application. If `AnAction` class uses a field to store data that has a shorter -lifetime and doesn't clear this data promptly, the data leaks. For example, any `AnAction` data that exists -only within the context of a `Project` causes the `Project` to be kept in memory after the user has closed it. +> **WARNING** Classes based on `AnAction` do not have class fields of any kind. +> This is because an instance of `AnAction` class exists for the entire lifetime of the application. +> If the `AnAction` class uses a field to store data that has a shorter lifetime and doesn't clear this data promptly, the data leaks. +> For example, any `AnAction` data that exists only within the context of a `Project` causes the `Project` to be kept in memory after the user has closed it. -### Principal Implementation Overrides +### Principal Implementation Overrides Every IntelliJ Platform action should override `AnAction.update()` and must override `AnAction.actionPerformed()`. -* An action's method `AnAction.update()` is called by the IntelliJ Platform framework to update the state of an action. +* An action's method `AnAction.update()` is called by the IntelliJ Platform framework to update an action state. The state (enabled, visible) of an action determines whether the action is available in the UI of an IDE. - An object of type [`AnActionEvent`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java) is passed to this method, and it contains the information about the current context for the action. + An object of the [`AnActionEvent`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java) type is passed to this method and contains information about the current context for the action. Actions are made available by changing state in the [Presentation](upsource:///platform/platform-api/src/com/intellij/ide/presentation/Presentation.java) object associated with the event context. - As explained in [Overriding the `AnAction.update()` Method](#overriding-the-anactionupdate-method), it is vital `update()` methods _execute quickly_ and return execution to the IntelliJ Platform. -* An action's method `AnAction.actionPerformed()` is called by the IntelliJ Platform if it is available and selected by the user. + 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 available and selected by the user. This method does the heavy lifting for the action - it contains the code executed when the action gets invoked. - The `actionPerformed()` method also receives `AnActionEvent` as a parameter, which is used to access projects, files, selection, etc. + The `actionPerformed()` method also receives `AnActionEvent` as a parameter, which is used to access projects, files, selection, etc. See [Overriding the `AnAction.actionPerformed()` Method](#overriding-the-anactionactionperformed-method) for more information. - -There are other methods to override in the `AnAction` class, such as for changing the default `Presentation` object for the action. -There is also a use case for overriding action constructors when registering them with dynamic action groups, which is demonstrated in the [Grouping Actions](/tutorials/action_system/grouping_action.md#adding-child-actions-to-the-dynamic-group) tutorial. + +There are other methods to override in the `AnAction` class, such as changing the default `Presentation` object for the action. +There is also a use case for overriding action constructors when registering them with dynamic action groups, demonstrated in the [Grouping Actions](/tutorials/action_system/grouping_action.md#adding-child-actions-to-the-dynamic-group) tutorial. However, the `update()` and `actionPerformed()` methods are essential to basic operation. ### Overriding the AnAction.update Method The method `AnAction.update()` is periodically called by the IntelliJ Platform in response to user gestures. The `update()` method gives an action to evaluate the current context and enable or disable its functionality. -> **WARNING** The `AnAction.update()` method can be called frequently, and on a UI thread. +> **WARNING** The `AnAction.update()` method can be called frequently and on a UI thread. This method needs to _execute very quickly_; no real work should be performed in this method. For example, checking selection in a tree or a list is considered valid, but working with the file system is not. -> **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 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. -Additional context information is available using the method `AnActionEvent.getData()`. +Context information is available from the methods of `AnActionEvent`, providing information such as the Presentation and whether the action is triggered by a Toolbar. +Additional context information is available using the method `AnActionEvent.getData()`. Keys defined in [`CommonDataKeys`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/CommonDataKeys.java) are passed to the `getData()` method to retrieve objects such as `Project`, `Editor`, `PsiFile`, and other information. Accessing this information is relatively light-weight and is suited for `AnAction.update()`. @@ -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()`. The default `Presentation` object is a set of descriptive information about a menu or toolbar action. -Every context for an action - it might appear in multiple menus, toolbars, or Navigation search locations - has a unique presentation. -Attributes such as an action's text, description, and icons, as well as visibility and enable/disable state, are stored in the presentation. +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 and visibility and enable/disable state, are stored in the presentation. The attributes in a presentation get initialized from the [action registration](#registering-actions). However, some can be changed at runtime using the methods of the `Presentation` object associated with an action. @@ -79,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. Toolbar actions display their respective icons for the disabled state. -The visibility of a disabled action in a menu depends on whether the host menu (e.g. "ToolsMenu") containing the action has the `compact` attribute set. -See [Grouping Actions](#grouping-actions) for more information about the `compact` attribute, and the visibility of menu actions. +The visibility of a disabled action in a menu depends on whether the host menu (e.g., "ToolsMenu") containing the action has the `compact` attribute set. +See [Grouping Actions](#grouping-actions) for more information about the `compact` attribute and menu actions' visibility. -> **NOTE** If an action is added to a toolbar, its `update()` can be called if there was any user activity or focus transfer. -If the action's availability changes in the absence of these events, then call [`ActivityTracker.getInstance().inc()`](upsource:///platform/platform-api/src/com/intellij/ide/ActivityTracker.java) to notify the action subsystem to update all toolbar actions. +> **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. -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 -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. -Using the `AnActionEvent` methods and `CommonDataKeys`, objects such as the `Project`, `Editor`, `PsiFile`, and other information is available. +By using the `AnActionEvent` methods and `CommonDataKeys`, objects such as the `Project`, `Editor`, `PsiFile`, and other information is available. For example, the `actionPerformed()` method can modify, remove, or add PSI elements to a file open in the editor. The code that executes in the `AnAction.actionPerformed()` method should execute efficiently, but it does not have to meet the same stringent requirements as the `update()` method. -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 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 `` of the plugin. -An action must have a unique identifier for each place it is used in the IDE UI, even though the FQN of the implementation is the same. +An action must have a unique identifier for each place. +It is used in the IDE UI, even though the FQN of the implementation is the same. Definitions of identifiers for the standard IntelliJ Platform actions are in [`IdeActions`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java). ### Grouping Actions -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. Subgroups of a group can form submenus of a menu. -Actions can be included in multiple groups, and thus appear in multiple places within the IDE UI. +Actions can be included in multiple groups, and thus appear in different places within the IDE UI. An action must have a unique identifier for each place it appears in the IDE UI. See the [Action Declaration Reference](#action-declaration-reference) section for information about how to specify locations in the IDE UI. #### Presentation -For every place where the action appears, a new [`Presentation`](upsource:///platform/platform-api/src/com/intellij/ide/presentation/Presentation.java) is created. -Therefore the same action can have different text or icons when it appears in different places of the user interface. +A new [`Presentation`](upsource:///platform/platform-api/src/com/intellij/ide/presentation/Presentation.java) gets created for every place where the action appears. +Therefore, the same action can have different text or icons when it appears in different places of the user interface. Different presentations for the action are created by copying the Presentation returned by the `AnAction.getTemplatePresentation()` method. #### Compact Attribute @@ -141,16 +142,16 @@ All other combinations of `compact`, visibility, and enablement produce N/A for See the [Grouping Actions](/tutorials/action_system/grouping_action.md) tutorial for examples of creating action groups. ## Registering Actions -There are two main ways to register an action: either by listing it in the `` 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 `` section of a plugin's `plugin.xml` file or through code. ### Registering Actions in plugin.xml -Registering actions in `plugin.xml` is demonstrated in the following reference examples, which document all elements and attributes that can be used in the `` 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 `` section and describe each element's meaning. #### Setting the Override-Text Element for an Action > **TIP** Beginning in 2020.1, an alternate version of an action's menu text can be declared for use depending on where an action appears. -By using the `` 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 `` element introduced in 2020.1 of the IntelliJ Platform, the menu text for an action can be different depending on context: menu location, toolbar, etc. In the `action` element reference example (below) with `id` attribute `VssIntegration.GarbageCollection`, the default is to use the menu text "Garbage Collector: Collect _Garbage." The `add-to-group` element declares the action is added to the Tools Menu. @@ -160,7 +161,7 @@ The Tools Menu is part of the Main Menu, so the displayed menu text is "Collect A different context, such as searching for the action using **Help \| Find Action...**, displays the default text "Garbage Collector: Collect _Garbage" to give the user additional information about the action. A second `override-text` element uses `place` and `use-text-of-place` attributes to declare the same version of the text used in the Main Menu is also used in the Editor Popup Menu. -Additional `override-text` elements could be used to specify additional places where the Main Menu text should be used. +Additional `override-text` elements could be used to specify other places where the Main Menu text should be used. An example of using `` 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 `` is demonstrated in the [Creating Actions]( 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. -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. 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 messages.BasicActionsBundle ``` For Actions, the `key` in property files incorporates the action `id` in this specific structure: -* `action..text=Translated Action Text` -* `action..description=Translated Action Description` +* `action..text=Translated Action Text` +* `action..description=Translated Action Description` If `` is used for an action `id`, the `key` includes the `` attribute: -* `action...text=Place-dependent Translated Action Text` -* `action...description=Place-dependent Translated Action Description` +* `action...text=Place-dependent Translated Action Text` +* `action...description=Place-dependent Translated Action Description` For Groups, the `key` in the property files incorporates the group `id` in this specific structure: -* `group..text=Translated Group Text` -* `group..description=Translated Group Description` +* `group..text=Translated Group Text` +* `group..description=Translated Group Description` See [Extending DefaultActionGroup](/tutorials/action_system/grouping_action.md#extending-defaultactiongroup) for a tutorial of localizing Actions and Groups. - + #### 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). -Group IDs for the IntelliJ Platform are defined in [`PlatformActions.xml`](upsource:///platform/platform-resources/src/idea/PlatformActions.xml). +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). 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 - @@ -234,7 +235,7 @@ This, and additional information can also be found by using the [Code Completion to which the action is added. The group must be implemented by an instance of the DefaultActionGroup class. The mandatory "anchor" attribute specifies the position of the - action in the group relative to other actions. It can have the values + action in the relative to other actions. It can have the values "first", "last", "before" and "after". The "relative-to-action" attribute is mandatory if the anchor is set to "before" and "after", and specifies the action before or after which @@ -249,12 +250,12 @@ This, and additional information can also be found by using the [Code Completion keystroke of the action. The mandatory "keymap" attribute specifies the keymap for which 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 - element below means the specified shortcut should be removed from + element below means the specified shortcut should be removed from the specified action. The optional "replace-all" attribute in the third - 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. --> @@ -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. The mandatory "keystroke" attribute specifies the clicks and 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; "shift", "control", "meta", "alt", "altGraph" for the modifier keys; "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 element. See for documentation. --> - - - @@ -317,14 +318,14 @@ This, and additional information can also be found by using the [Code Completion ### Registering Actions 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. -* Second, the action needs to be added to one or more groups. +* 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. 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 -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. +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. To get a Swing component from such an object, call the respective `getComponent()` method. -If an action toolbar is attached to a specific component (for example, a panel in a tool window), call `ActionToolbar.setTargetComponent()` and pass the instance of the related component as a parameter. -Setting the target ensures that the state of the toolbar buttons depends on the state of the related component, and not on the current focus location within the IDE frame. +If an action toolbar is attached to a specific component (for example, a panel in a tool window), call `ActionToolbar.setTargetComponent()` and pass the related component's instance as a parameter. +Setting the target ensures that the toolbar buttons' state depends on the state of the related component, not on the current focus location within the IDE frame. diff --git a/basics/architectural_overview/documents.md b/basics/architectural_overview/documents.md index e163d343c..4a7f15c46 100644 --- a/basics/architectural_overview/documents.md +++ b/basics/architectural_overview/documents.md @@ -3,7 +3,7 @@ title: Documents --- -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`. 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? -You may perform any operations that access or modify the file contents on "plain text" level (as a sequence of characters, not as a tree of PSI elements). +You may perform any operations that access or modify the file contents on the "plain text" level (as a sequence of characters, not as a tree of PSI elements). ## Where does a Document come from? -Document instances are created when some operation needs to access the text contents of a file (in particular, this is needed to build the PSI for a file). +Document instances are created when some operation needs to access the text contents of a file (in particular, this is necessary to build the PSI for a file). Also, document instances not linked to any virtual files can be created temporarily, for example, representing the contents of a text editor field in a dialog. ## How long does a Document persist? -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. +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. > **WARNING** Storing `Document` references in long-term data structures of a plugin will cause memory leaks. ## 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()`. ## 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? -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()`). -`executeCommand()` calls can be nested, and the outermost `executeCommand()` call is added to the undo stack. +The general read/write action rules are in effect. +Besides, any operations which modify the contents of the document must be wrapped in a command (`CommandProcessor.getInstance().executeCommand()`). +`executeCommand()` calls can be nested, and the outermost `executeCommand()` call is added to the undo stack. If multiple documents are modified within a command, undoing this command will, by default, show a confirmation dialog to the user. 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? -[`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`. +[`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`. diff --git a/basics/architectural_overview/file_view_providers.md b/basics/architectural_overview/file_view_providers.md index 3819fca09..94a617c6f 100644 --- a/basics/architectural_overview/file_view_providers.md +++ b/basics/architectural_overview/file_view_providers.md @@ -7,9 +7,9 @@ A file view provider ([`FileViewProvider`](upsource:///platform/core-api/src/com For example, a JSPX page has a separate PSI tree for the Java code in it (`PsiJavaFile`), a separate tree for the XML code (`XmlFile`), and a separate tree for JSP as a whole ([`JspFile`](upsource:///java/jsp-openapi/src/com/intellij/psi/jsp/JspFile.java)). -Each of the PSI trees covers the entire contents of the file, and contains special "outer language elements" in the places where contents in a different language can be found. +Each of the PSI trees covers the entire contents of the file and contains special "outer language elements" in the places where contents in a different language can be found. -A `FileViewProvider` instance corresponds to a single `VirtualFile`, a single `Document`, and can be used to retrieve multiple `PsiFile` instances. +A `FileViewProvider` instance corresponds to a single `VirtualFile`, a single `Document`, and can retrieve multiple `PsiFile` instances. ## How do I get a FileViewProvider? @@ -19,7 +19,8 @@ A `FileViewProvider` instance corresponds to a single `VirtualFile`, a single `D ## What can I do with a FileViewProvider? * To get the set of all languages for which PSI trees exist in a file: `fileViewProvider.getLanguages()` -* To get the PSI tree for a particular language: `fileViewProvider.getPsi(language)`. For example, to get the PSI tree for XML, use `fileViewProvider.getPsi(XMLLanguage.INSTANCE)`. +* To get the PSI tree for a particular language: `fileViewProvider.getPsi(language)`. + For example, to get the PSI tree for XML, use `fileViewProvider.getPsi(XMLLanguage.INSTANCE)`. * To find an element of a particular language at the specified offset in the file: `fileViewProvider.findElementAt(offset, language)` ## How do I extend the FileViewProvider? @@ -36,4 +37,4 @@ Register as follows in `plugin.xml`: ``` -Where `%file_type%` refers to the type of the file being created (for example, "JFS"). \ No newline at end of file +Where `%file_type%` refers to the type of the file being created (for example, "JFS"). diff --git a/basics/architectural_overview/general_threading_rules.md b/basics/architectural_overview/general_threading_rules.md index dfcf2a6ff..9e1be83e1 100644 --- a/basics/architectural_overview/general_threading_rules.md +++ b/basics/architectural_overview/general_threading_rules.md @@ -5,18 +5,18 @@ title: General Threading Rules ## 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: -- PSI +- PSI - VFS - project root model. -**Reading** data is allowed from any thread. -Reading data from the UI thread does not require any special effort. +**Reading** data is allowed from any thread. +Reading data from the UI thread does not require any special effort. However, read operations performed from any other thread need to be wrapped in a read action by using `ApplicationManager.getApplication().runReadAction()` or, shorter, [`ReadAction`](upsource:///platform/core-api/src/com/intellij/openapi/application/ReadAction.java) `run()`/`compute()`. The corresponding objects are not guaranteed to survive between several consecutive read actions. -As a rule of thumb, whenever starting a read action, check if PSI/VFS/project/module is still valid. +As a rule of thumb, whenever starting a read action, check if the PSI/VFS/project/module is still valid. **Writing** data is only allowed from the UI thread, and write operations always need to be wrapped in a write action with `ApplicationManager.getApplication().runWriteAction()` or, shorter, [`WriteAction`](upsource:///platform/core-api/src/com/intellij/openapi/application/WriteAction.java) `run()`/`compute()`. Modifying the model is only allowed from write-safe contexts, including user actions and `invokeLater()` calls from them (see the next section). @@ -26,60 +26,56 @@ You may not modify PSI, VFS, or project model from inside UI renderers or `Swing ## 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()`. -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` -: The operation will be executed after all modal dialogs are closed. Note that if any of the open (unrelated) project displays a per-project modal dialog, the action will be executed after the dialog is closed. +: The operation will be executed after all modal dialogs are closed. If any of the open (unrelated) project displays a per-project modal dialog, the action will be performed after the dialog is closed. `ModalityState.stateForComponent()` -: The operation can be executed when the topmost shown dialog is the one that contains the specified component or is one of its parent dialogs. +: The operation can be executed when the topmost shown dialog is the one that contains the specified component or is one of its parent dialogs. None specified -: `ModalityState.defaultModalityState()` will be used. In most cases, this is the optimal choice, that uses current modality state when invoked from UI thread, and has special handling for background processes started with `ProgressManager`: `invokeLater()` from such a process may run in the same dialog that the process started. +: `ModalityState.defaultModalityState()` will be used. This is the optimal choice in most cases that uses the current modality state when invoked from UI thread. It has special handling for background processes started with `ProgressManager`: `invokeLater()` from such a process may run in the same dialog that the process started. `ModalityState.any()` : The operation will be executed as soon as possible regardless of modal dialogs. Please note that modifying PSI, VFS, or project model is prohibited from such runnables. -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. ## Background processes and `ProcessCanceledException` -Background progresses are managed by [`ProgressManager`](upsource:///platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java) class, -which has plenty of methods to execute the given code with a modal (dialog), non-modal (visible in the status bar), or invisible progress. +Background progresses are managed by [`ProgressManager`](upsource:///platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java) class, which has plenty of methods to execute the given code with a modal (dialog), non-modal (visible in the status bar), or invisible progress. In all cases, the code is executed on a background thread, which is associated with a [`ProgressIndicator`](upsource:///platform/core-api/src/com/intellij/openapi/progress/ProgressIndicator.java) object. The current thread's indicator can be retrieved any time via `ProgressIndicatorProvider.getGlobalProgressIndicator()`. -For visible progresses, threads can use `ProgressIndicator` to notify the user about current status: -e.g., set text or visible fraction of the work done. +For visible progresses, threads can use `ProgressIndicator` to notify the user about current status: e.g., set text or visual fraction of the work done. -Progress indicators also provide means to handle cancellation of background processes, either by the user (pressing _Cancel_ button) -or from code (e.g., when the current operation becomes obsolete due to some changes in the project). +Progress indicators also provide means to handle cancellation of background processes, either by the user (pressing the _Cancel_ button) or from code (e.g., when the current operation becomes obsolete due to some changes in the project). The progress can be marked as canceled by calling `ProgressIndicator.cancel()`. The process reacts to this by calling `ProgressIndicator.checkCanceled()` (or `ProgressManager.checkCanceled()` if no indicator instance at hand). This call throws a special unchecked [`ProcessCanceledException`](upsource:///platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java) if the background process has been canceled. All code working with PSI, or in other kinds of background processes, must be prepared for [`ProcessCanceledException`](upsource:///platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java) being thrown from any point. -This exception should never be logged, but rethrown, and it'll be handled in the infrastructure that started the process. +This exception should never be logged but rethrown, and it'll be handled in the infrastructure that started the process. -The `checkCanceled()` should be called often enough to guarantee smooth cancellation of the process. +The `checkCanceled()` should be called often enough to guarantee the process's smooth cancellation. PSI internals have a lot of `checkCanceled()` calls inside. If a process does lengthy non-PSI activity, insert explicit `checkCanceled()` calls so that it happens frequently, e.g., on each _Nth_ loop iteration. ## Read Action Cancellability -Background threads shouldn't take plain read actions for a long time. The reason is that if the UI thread needs a write action (e.g., the user types something), -it must be acquired as soon as possible. Otherwise, the UI will freeze until all background threads have released their read actions. +Background threads shouldn't take plain read actions for a long time. +The reason is that if the UI thread needs a write action (e.g., the user types something), it must be acquired as soon as possible. +Otherwise, the UI will freeze until all background threads have released their read actions. The best-known approach is to cancel background read actions whenever there's a write action about to occur, and restart that background read action later from scratch. Editor highlighting, code completion, Goto Class/File/... actions all work like this. -To achieve that, the lengthy background operation is started with a `ProgressIndicator`, and a dedicated listener -cancels that indicator when write action is started. -The next time the background thread calls `checkCanceled()`, a `ProcessCanceledException` is thrown, -and the thread should stop its operation (and finish the read action) as soon as possible. - +To achieve that, the lengthy background operation is started with a `ProgressIndicator`, and a dedicated listener cancels that indicator when write action is initiated. +The next time the background thread calls `checkCanceled()`, a `ProcessCanceledException` is thrown, and the thread should stop its operation (and finish the read action) as soon as possible. + There are two recommended ways of doing this: * If on UI thread, call `ReadAction.nonBlocking()` which returns [`NonBlockingReadAction`](upsource:///platform/core-api/src/com/intellij/openapi/application/NonBlockingReadAction.java) diff --git a/basics/architectural_overview/modifying_psi.md b/basics/architectural_overview/modifying_psi.md index 0fedf4763..ecaf6de2f 100644 --- a/basics/architectural_overview/modifying_psi.md +++ b/basics/architectural_overview/modifying_psi.md @@ -3,44 +3,33 @@ title: Modifying the PSI --- -The PSI is a read-write representation of the source code as a tree of elements corresponding to the structure of a source -file. You can modify the PSI by *adding*, *replacing*, and *deleting* PSI elements. +The PSI is a read-write representation of the source code as a tree of elements corresponding to a source file's structure. +You can modify the PSI by *adding*, *replacing*, and *deleting* PSI elements. -To perform these operations, you use methods such as `PsiElement.add()`, `PsiElement.delete()`, and `PsiElement.replace()`, -as well as other methods defined in the `PsiElement` interface that let you process multiple elements in a single -operation, or to specify the exact location in the tree where an element needs to be added. - -Just as document operations, PSI modifications need to be wrapped in a write action and in a command (and therefore -can only be performed in the event dispatch thread). See [the Documents article](documents.md#what-are-the-rules-of-working-with-documents) -for more information on commands and write actions. +To perform these operations, you use methods such as `PsiElement.add()`, `PsiElement.delete()`, and `PsiElement.replace()`, as well as other methods defined in the `PsiElement` interface that let you process multiple elements in a single operation, or to specify the exact location in the tree where an element needs to be added. +Like document operations, PSI modifications need to be wrapped in a write action and in command (and can only be performed in the event dispatch thread). +See [the Documents article](documents.md#what-are-the-rules-of-working-with-documents) for more information on commands and write actions. ## Creating the New PSI -The PSI elements to add to the tree, or to replace existing PSI elements, are normally *created from text*. -In the most general case, you use the `createFileFromText()` method of [`PsiFileFactory`](upsource:///platform/core-api/src/com/intellij/psi/PsiFileFactory.java) -to create a new file that contains the code construct which you need to add to the tree or to use as a replacement -for an existing element, traverse the resulting tree to locate the specific element that you need, and then pass that -element to `add()` or `replace()`. +The PSI elements to add to the tree or replace existing PSI elements are usually *created from text*. +In the most general case, you use the `createFileFromText()` method of [`PsiFileFactory`](upsource:///platform/core-api/src/com/intellij/psi/PsiFileFactory.java) to create a new file that contains the code construct which you need to add to the tree or to use as a replacement for an existing element, traverse the resulting tree to locate the specific part that you need, and then pass that element to `add()` or `replace()`. -Most languages provide factory methods which let you create specific code constructs more easily. For example, -the [`PsiJavaParserFacade`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiJavaParserFacade.java) class -contains methods such as `createMethodFromText()`, which creates a Java method from the given text. +Most languages provide factory methods that let you create specific code constructs more easily. +For example, the [`PsiJavaParserFacade`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiJavaParserFacade.java) class contains methods such as `createMethodFromText()`, which creates a Java method from the given text. -When you're implementing refactorings, intentions or inspection quickfixes that work with existing code, the text that -you pass to the various `createFromText()` methods will combine hard-coded fragments and fragments of code taken from -the existing file. For small code fragments (individual identifiers), you can simply append the text from the existing -code to the text of the code fragment you're building. In that case, you need to make sure that the resulting text is -syntactically correct, otherwise the `createFromText()` method will throw an exception. +When you're implementing refactorings, intentions, or inspection quickfixes that work with existing code, the text that you pass to the various `createFromText()` methods will combine hard-coded fragments and fragments of code taken from the existing file. +For small code fragments (individual identifiers), you can simply append the text from the existing code to the text of the code fragment you're building. +In that case, you need to make sure that the resulting text is syntactically correct. Otherwise the `createFromText()` method will throw an exception. -For larger code fragments, it's best to perform the modification in several steps: +For larger code fragments, it's best to perform the modification in several steps: - * create a replacement tree fragment from text, leaving placeholders for the user code fragments; + * create a replacement tree fragment from the text, leaving placeholders for the user code fragments; * replace the placeholders with the user code fragments; * replace the element in the original source file with the replacement tree. -This ensures that the formatting of the user code is preserved and that the modification doesn't introduce any unwanted -whitespace changes. +This ensures that the user code's formatting is preserved and that the modification doesn't introduce any unwanted whitespace changes. As an example of this approach, see the quickfix in the `ComparingReferencesInspection` example: @@ -64,44 +53,33 @@ equalsCall.getArgumentList().getExpressions()[0].replace(rExpr); PsiExpression result = (PsiExpression) binaryExpression.replace(equalsCall); ``` -Just as everywhere else in the IntelliJ Platform API, the text passed to `createFileFromText()` and other `createFromText()` -methods must use only `\n` as line separators. +Just as everywhere else in the IntelliJ Platform API, the text passed to `createFileFromText()` and other `createFromText()` methods must use only `\n` as line separators. ## Maintaining Tree Structure Consistency -The PSI modification methods do not restrict you in the way you can build the resulting tree structure. For example, -when working with a Java class, you can add a `for` statement as a direct child of a `PsiMethod` element, even though -the Java parser will never produce such a structure (the `for` statement will always be a child of the `PsiCodeBlock`) -representing the method body). Modifications that produce incorrect tree structures may appear to work, but they will -lead to problems and exceptions later. Therefore, you always need to ensure that the structure you built with PSI -modification operations is the same as what the parser would produce when parsing the code that you've built. +The PSI modification methods do not restrict you in the way you can build the resulting tree structure. +For example, when working with a Java class, you can add a `for` statement as a direct child of a `PsiMethod` element, even though the Java parser will never produce such a structure (the `for` statement will always be a child of the `PsiCodeBlock`) representing the method body). +Modifications that produce incorrect tree structures may appear to work, but they will lead to problems and exceptions later. +Therefore, you always need to ensure that the structure you built with PSI modification operations is the same as what the parser would produce when parsing the code that you've created. -To make sure you're not introducing inconsistencies, you can call `PsiTestUtil.checkFileStructure()` in the tests for -your action that modifies the PSI. This method ensures that the structure you've built is the same as what the parser produces. +To make sure you're not introducing inconsistencies, you can call `PsiTestUtil.checkFileStructure()` in the tests for your action that modifies the PSI. +This method ensures that the structure you've built is the same as what the parser produces. ## Whitespaces and Imports -When working with PSI modification functions, you should never create individual whitespace nodes (spaces or line breaks) -from text. Instead, all whitespace modifications are performed by the formatter, which follows the code style settings -selected by the user. Formatting is automatically performed at the end of every command, and if you need, you can -also perform it manually using the `reformat(PsiElement)` method in the -[`CodeStyleManager`](upsource:///platform/core-api/src/com/intellij/psi/codeStyle/CodeStyleManager.java) class. +When working with PSI modification functions, you should never create individual whitespace nodes (spaces or line breaks) from the text. +Instead, all whitespace modifications are performed by the formatter, which follows the code style settings selected by the user. +Formatting is automatically performed at the end of every command, and if you need, you can also perform it manually using the `reformat(PsiElement)` method in the [`CodeStyleManager`](upsource:///platform/core-api/src/com/intellij/psi/codeStyle/CodeStyleManager.java) class. -Also, when working with Java code (or with code in other languages with a similar import mechanism such as Groovy or Python), -you should never create imports manually. Instead, you should insert fully-qualified names into the code you're -generating, and then call the `shortenClassReferences()` method in the -[`JavaCodeStyleManager`](upsource:///java/java-psi-api/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java) -(or the equivalent API for the language you're working with). This ensures that the imports are created according to -the user's code style settings and inserted into the correct place of the file. +Also, when working with Java code (or with code in other languages with a similar import mechanism such as Groovy or Python), you should never create imports manually. +Instead, you should insert fully-qualified names into the code you're generating, and then call the `shortenClassReferences()` method in the [`JavaCodeStyleManager`](upsource:///java/java-psi-api/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java) (or the equivalent API for the language you're working with). +This ensures that the imports are created according to the user's code style settings and inserted into the file's correct place. -## Combining PSI and Document Modifications - -In some cases, you need to perform a PSI modification and then to perform an operation on the document you've just -modified through the PSI (for example, start a live template). In this case, you need to call a special method that -completes the PSI-based post-processing (such as formatting) and commits the changes to the document. The method -you need to call is called `doPostponedOperationsAndUnblockDocument()`, and it's defined in the -[`PsiDocumentManager`](upsource:///platform/core-api/src/com/intellij/psi/PsiDocumentManager.java) class. +## 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. diff --git a/basics/architectural_overview/navigating_psi.md b/basics/architectural_overview/navigating_psi.md index 7ee76ba2a..7344dcdba 100644 --- a/basics/architectural_overview/navigating_psi.md +++ b/basics/architectural_overview/navigating_psi.md @@ -3,24 +3,20 @@ title: Navigating the PSI --- -There are three main ways to navigate the PSI: *top-down*, *bottom-up*, and using *references*. In the first scenario, -you have a PSI file or another higher-level element (for example, a method), and you need to find all elements that match a -specified condition (for example, all variable declarations). In the second scenario, you have a specific point -in the PSI tree (for example, the element at caret) and need to find out something about its context (for example, -the element in which it has been declared). Finally, *references* allow you to navigate from the use of an element -(e.g., a method call) to the declaration (the method being called) and back. References are described in a -[separate topic](psi_references.md). +There are three main ways to navigate the PSI: *top-down*, *bottom-up*, and *references*. +In the first scenario, you have a PSI file or another higher-level element (for example, a method). You need to find all elements that match a specified condition (for example, all variable declarations). +In the second scenario, you have a specific point in the PSI tree (for example, the element at caret) and need to find out something about its context (for example, the element in which it has been declared). +Finally, *references* allow you to navigate from the usages of an element (e.g., a method call) to the declaration (the method being called) and back. +References are described in a [separate topic](psi_references.md). ## Top-Down Navigation -The most common way to perform top-down navigation is to use a *visitor*. To use a visitor, you create a class -(usually an anonymous inner class) that extends the base visitor class, override the methods that handle the elements -you're interested in, and pass the visitor instance it to `PsiElement.accept()`. +The most common way to perform top-down navigation is to use a *visitor*. +To use a visitor, you create a class (usually an anonymous inner class) that extends the base visitor class, overrides the methods that handle the elements you're interested in, and passes the visitor instance to `PsiElement.accept()`. -The base classes for visitors are language-specific. For example, if you need to process elements in a Java file, -you extend `JavaRecursiveElementVisitor` and override the methods corresponding to the Java element types you're -interested in. +The base classes for visitors are language-specific. +For example, if you need to process elements in a Java file, you extend `JavaRecursiveElementVisitor` and override the methods corresponding to the Java element types you're interested in. The following snippet shows the use of a visitor to find all Java local variable declarations: @@ -34,26 +30,23 @@ file.accept(new JavaRecursiveElementVisitor() { }); ``` -In many cases, you can also use more specific APIs for top-down navigation. For example, if you need to get a list of -all methods in a Java class, you can do that using a visitor, but a much easier way to do that is to call `PsiClass.getMethods()`. +In many cases, you can also use more specific APIs for top-down navigation. +For example, if you need to get a list of all methods in a Java class, you can use a visitor, but a much easier way to do that is calling `PsiClass.getMethods()`. -[`PsiTreeUtil`](upsource:///platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java) contains a number of -general-purpose, language-independent functions for PSI tree navigation, some of which (for example, `findChildrenOfType()`) -perform top-down navigation. +[`PsiTreeUtil`](upsource:///platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java) contains a number of general-purpose, language-independent functions for PSI tree navigation, some of which (for example, `findChildrenOfType()`) perform top-down navigation. ## Bottom-Up Navigation -The starting point for bottom-up navigation is either a specific element in the PSI tree (for example, the result of -resolving a reference), or an offset. If you have an offset, you can find the corresponding PSI element by calling -`PsiFile.findElementAt()`. This method returns the element at the lowest level of the tree (for example, an identifier), -and you need to navigate the tree up if you want to determine the broader context. +The starting point for bottom-up navigation is either a specific element in the PSI tree (for example, the result of resolving a reference) or an offset. +If you have an offset, you can find the corresponding PSI element by calling `PsiFile.findElementAt()`. +This method returns the element at the lowest level of the tree (for example, an identifier), and you need to navigate the tree up if you want to determine the broader context. -In most cases, bottom-up navigation is performed by calling `PsiTreeUtil.getParentOfType()`. This method goes up the -tree until it finds the element of the type you've specified. For example, to find the containing method, you call -`PsiTreeUtil.getParentOfType(element, PsiMethod.class)`. +In most cases, bottom-up navigation is performed by calling `PsiTreeUtil.getParentOfType()`. +This method goes up the tree until it finds the element of the type you've specified. +For example, to find the containing method, you call `PsiTreeUtil.getParentOfType(element, PsiMethod.class)`. -In some cases, you can also use specific navigation methods. For example, to find the class where a method is contained, -you call `PsiMethod.getContainingClass()`. +In some cases, you can also use specific navigation methods. +For example, to find the class where a method is contained, you call `PsiMethod.getContainingClass()`. The following snippet shows how these calls can be used together: @@ -64,5 +57,4 @@ PsiMethod containingMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.clas PsiClass containingClass = containingMethod.getContainingClass(); ``` -To see how the navigation works in practice, please refer to the -[code sample](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/psi_demo/src/main/java/org/intellij/sdk/psi/PsiNavigationDemoAction.java). +To see how the navigation works in practice, please refer to the [code sample](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/psi_demo/src/main/java/org/intellij/sdk/psi/PsiNavigationDemoAction.java). diff --git a/basics/architectural_overview/psi.md b/basics/architectural_overview/psi.md index 41aa5e69d..9362db3a8 100644 --- a/basics/architectural_overview/psi.md +++ b/basics/architectural_overview/psi.md @@ -3,11 +3,11 @@ title: Program Structure Interface (PSI) --- -The Program Structure Interface, commonly referred to as just PSI, is the layer in the _IntelliJ Platform_ that is responsible for parsing files and creating the syntactic and semantic code model that powers so many of the platform's features. +The Program Structure Interface, commonly referred to as just PSI, is the layer in the _IntelliJ Platform_ responsible for parsing files and creating the syntactic and semantic code model that powers so many of the platform's features. * [PSI Files](/basics/architectural_overview/psi_files.md) * [File View Providers](/basics/architectural_overview/file_view_providers.md) * [PSI Elements](/basics/architectural_overview/psi_elements.md) -> **TIP** A very helpful tool for debugging the PSI implementation is the [PsiViewer plugin](https://plugins.jetbrains.com/plugin/227-psiviewer). -It can show you the structure of the PSI tree, the properties of every PSI element and highlight its text range. +> **TIP** A useful tool for debugging the PSI implementation is the [PsiViewer plugin](https://plugins.jetbrains.com/plugin/227-psiviewer). +> It can show you the PSI tree structure, the properties of every PSI element, and highlight its text range. diff --git a/basics/architectural_overview/psi_elements.md b/basics/architectural_overview/psi_elements.md index a41a13ded..179bbffb9 100644 --- a/basics/architectural_overview/psi_elements.md +++ b/basics/architectural_overview/psi_elements.md @@ -1,19 +1,26 @@ --- title: 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. +A PSI (Program Structure Interface) file represents a hierarchy of PSI elements (so-called _PSI trees_). +A single PSI file (itself being a PSI element) may contain several PSI trees in specific programming languages. +A PSI element, in its turn, can have child PSI elements. -PSI elements and operations at the level of individual PSI elements are used to explore the internal structure of source code as it is interpreted by the **IntelliJ Platform**. For example, you can use PSI elements to perform code analysis, such as [code inspections](https://www.jetbrains.com/help/idea/code-inspection.html) or [intention actions](https://www.jetbrains.com/idea/help/intention-actions.html). +PSI elements and operations at the level of individual PSI elements are used to explore the source code's internal structure as it is interpreted by the **IntelliJ Platform**. +For example, you can use PSI elements to perform code analysis, such as [code inspections](https://www.jetbrains.com/help/idea/code-inspection.html) or [intention actions](https://www.jetbrains.com/idea/help/intention-actions.html). The [`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) class is the common base class for PSI elements. ## How do I get a PSI element? -* From an action: `e.getData(LangDataKeys.PSI_ELEMENT)`. Note: if an editor is currently open and the element under caret is a reference, this will return the result of resolving the reference. This may or may not be what you need. -* From a file by offset: `PsiFile.findElementAt()`. Note: this returns the lowest level element ("leaf") at the specified offset, which is normally a lexer token. -Most likely you should use `PsiTreeUtil.getParentOfType()` to find the element you really need. +* From an action: `e.getData(LangDataKeys.PSI_ELEMENT)`. + Note: if an editor is currently open and the element under caret is a reference, this will return the result of resolving the reference. + This may or may not be what you need. +* From a file by offset: `PsiFile.findElementAt()`. + Note: this returns the lowest level element ("leaf") at the specified offset, normally a lexer token. + Most likely, you should use `PsiTreeUtil.getParentOfType()` to find the element you really need. * By iterating through a PSI file: using a [`PsiRecursiveElementWalkingVisitor`](upsource:///platform/core-api/src/com/intellij/psi/PsiRecursiveElementWalkingVisitor.java). * By resolving a reference: `PsiReference.resolve()` diff --git a/basics/architectural_overview/psi_files.md b/basics/architectural_overview/psi_files.md index aacabeb3e..abbb9a074 100644 --- a/basics/architectural_overview/psi_files.md +++ b/basics/architectural_overview/psi_files.md @@ -3,11 +3,14 @@ title: PSI Files --- -A PSI (Program Structure Interface) file is the root of a structure representing the contents of a file as a hierarchy of elements in a particular programming language. +A PSI (Program Structure Interface) file is the root of a structure representing a file's contents as a hierarchy of elements in a particular programming language. The [`PsiFile`](upsource:///platform/core-api/src/com/intellij/psi/PsiFile.java) class is the common base class for all PSI files, while files in a specific language are usually represented by its subclasses. For example, the [`PsiJavaFile`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiJavaFile.java) class represents a Java file, and the [`XmlFile`](upsource:///xml/xml-psi-api/src/com/intellij/psi/xml/XmlFile.java) class represents an XML file. -Unlike `VirtualFile` and `Document`, which have application scope (even if multiple projects are open, each file is represented by the same `VirtualFile` instance), PSI has project scope (the same file is represented by multiple `PsiFile` instances if the file belongs to multiple projects open at the same time). +Unlike `VirtualFile` and `Document`, which have application scope (even if multiple projects are open, each file is represented by the same `VirtualFile` instance). +A PSI has project scope. +The same file is represented by one `PsiFile` instance for each open project to which the file belongs. +In contrast, `VirtualFile` and Document have application scope; files are represented by the same VirtualFile instance, even if multiple projects are open. ## How do I get a PSI file? @@ -27,7 +30,7 @@ To iterate over the elements in a file, use `psiFile.accept(new PsiRecursiveElem As PSI is language-dependent, PSI files are created through the [`Language`](upsource:///platform/core-api/src/com/intellij/lang/Language.java) object, by using the `LanguageParserDefinitions.INSTANCE.forLanguage(language).createFile(fileViewProvider)` method. -Like documents, PSI files are created on demand when the PSI is accessed for a particular file. +Like documents, PSI files are created on-demand when the PSI is accessed for a particular file. ## How long do PSI files persist? @@ -45,7 +48,8 @@ To save the PSI file to disk, use the [`PsiDirectory`](upsource:///platform/core ## How do I extend PSI? -PSI can be extended to support additional languages through custom language plugins. For more details on developing custom language plugins, see the [Custom Language Support](/reference_guide/custom_language_support.md) reference guide. +PSI can be extended to support additional languages through custom language plugins. +For more details on developing custom language plugins, see the [Custom Language Support](/reference_guide/custom_language_support.md) reference guide. ## What are the rules for working with PSI? diff --git a/basics/architectural_overview/psi_references.md b/basics/architectural_overview/psi_references.md index 53b09b4ef..b5304a8a5 100644 --- a/basics/architectural_overview/psi_references.md +++ b/basics/architectural_overview/psi_references.md @@ -3,11 +3,10 @@ title: PSI References --- -A *reference* in a PSI tree is an object that represents a link from a *usage* of a certain element in the code -to the corresponding *declaration*. *Resolving* a reference means locating the declaration to which a specific usage -refers. +A *reference* in a PSI tree is an object that represents a link from a *usage* of a particular element in the code to the corresponding *declaration*. *Resolving* a reference means locating the declaration to which a specific usage refers. -The most common type of references is defined by language semantics. For example, consider a simple Java method: +The most common type of reference is defined by language semantics. +For example, consider a simple Java method: ```java public void hello(String message) { @@ -15,84 +14,82 @@ public void hello(String message) { } ``` -This simple code fragment contains five references. The references created by the identifiers `String`, `System`, `out` and -`println` can be resolved to the corresponding declarations in the JDK: the `String` and `System` classes, the `out` field and the -`println` method. The reference created by the second occurrence of the `message` identifier in `println(message)` can be resolved to the -`message` parameter, declared by `String message` in the method header. +This simple code fragment contains five references. +The references created by the identifiers `String`, `System`, `out`, and `println` can be resolved to the corresponding declarations in the JDK: the `String` and `System` classes, the `out` field, and the `println` method. +The reference created by the second occurrence of the `message` identifier in `println(message)` can be resolved to the `message` parameter, declared by `String message` in the method header. -Note that `String message` is not a reference, and cannot be resolved. Instead, it's a _declaration_. It does not -refer to any name defined elsewhere; instead, it defines a name by itself. +Note that `String message` is not a reference and cannot be resolved. +Instead, it's a _declaration_. +It does not refer to any name defined elsewhere; instead, it defines a name by itself. A reference is an instance of a class implementing the [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) interface. -Note that references are distinct from PSI elements. References created by a PSI element are returned from -`PsiElement.getReferences()`, the underlying PSI element of a reference can be obtained from `PsiReference.getElement()`. +Note that references are distinct from PSI elements. +References created by a PSI element are returned from `PsiElement.getReferences()`, the underlying PSI element of a reference can be obtained from `PsiReference.getElement()`. -To *resolve* the reference - to locate the declaration being referenced - call `PsiReference.resolve()`. It's very -important to understand the difference between `PsiReference.getElement()` and `PsiReference.resolve()`. The former method returns the _source_ -of a reference, while the latter returns its _target_. In the example above, for the `message` reference, `getElement()` -will return the `message` identifier on the second line of the snippet, and `resolve()` will return the `message` identifier -on the first line (inside the parameter list). +To *resolve* the reference - to locate the declaration being referenced - call `PsiReference.resolve()`. +It's very important to understand the difference between `PsiReference.getElement()` and `PsiReference.resolve()`. +The former method returns the _source_ of a reference, while the latter returns its _target_. +In the example above, for the `message` reference, `getElement()` will return the `message` identifier on the second line of the snippet, and `resolve()` will return the `message` identifier on the first line (inside the parameter list). -The process of resolving references is distinct from parsing and is not performed at the same time. Moreover, it is -not always successful. If the code currently open in the IDE does not compile, or in other situations, it's normal -for `PsiReference.resolve()` to return `null` - all code working with references must be prepared to handle that. +The process of resolving references is distinct from parsing and is not performed at the same time. +Moreover, it is not always successful. +If the code currently open in the IDE does not compile, or in other situations, it's normal for `PsiReference.resolve()` to return `null` - all code working with references must be prepared to handle that. > **TIP** Please see also _Cache results of heavy computations_ in [Working with PSI efficiently](/reference_guide/performance/performance.md#working-with-psi-efficiently). ## Contributed References -In addition to references defined by the semantics of the programming language, the IDE recognizes many references -which are determined by the semantics of the APIs and frameworks used in code. Consider the following example: +In addition to references defined by the semantics of the programming language, the IDE recognizes many references determined by the semantics of the APIs and frameworks used in code. +Consider the following example: ```java File f = new File("foo.txt"); ``` -Here, "foo.txt" has no special meaning from the point of view of the Java syntax - it's just a string literal. However, -opening this example in IntelliJ IDEA and having a file called "foo.txt" in the same directory, one -can Ctrl/Cmd-Click on "foo.txt" and navigate to the file. This works because the IDE recognizes the -semantics of `new File(...)` and _contributes a reference_ into the string literal passed as a parameter to the method. +Here, "foo.txt" has no special meaning from the point of view of the Java syntax - it's just a string literal. +However, opening this example in IntelliJ IDEA and having a file called "foo.txt" in the same directory, one can Ctrl/Cmd-Click on "foo.txt" and navigate to the file. +This works because the IDE recognizes the semantics of `new File(...)` and _contributes a reference_ into the string literal passed as a parameter to the method. -Typically, references can be contributed to elements that don't have their own references, such as string literals -and comments. References are also often contributed to non-code files, such as XML or JSON. +Typically, references can be contributed to elements that don't have their own references, such as string literals and comments. +References are also often contributed to non-code files, such as XML or JSON. -Contributing references is one of the most common ways to extend an existing language. For example, your plugin can -contribute references to Java code, even though the Java PSI is part of the platform and not defined in your plugin. +Contributing references is one of the most common ways to extend an existing language. +For example, your plugin can contribute references to Java code, even though the Java PSI is part of the platform and not defined in your plugin. To contribute references, see the [reference contributor tutorial](/tutorials/custom_language_support/reference_contributor.md). ## References with Optional or Multiple Resolve Results -In the simplest case, a reference resolves to a single element, and if resolving fails, the -code is incorrect, and the IDE needs to highlight it as an error. However, there are cases when the situation is different. +In the simplest case, a reference resolves to a single element, and if resolving fails, the code is incorrect, and the IDE needs to highlight it as an error. +However, there are cases when the situation is different. -The first case is *soft references*. Consider the `new File("foo.txt")` example above. If the IDE can't find -the file "foo.txt", it doesn't mean that an error needs to be highlighted - maybe the file is only available at runtime. +The first case is *soft references*. +Consider the `new File("foo.txt")` example above. +If the IDE can't find the file "foo.txt", it doesn't mean that an error needs to be highlighted - maybe the file is only available at runtime. Such references return `true` from the `PsiReference.isSoft()` method. -The second case is *polyvariant references*. Consider the case of a JavaScript program. JavaScript is a dynamically -typed language, so the IDE cannot always precisely determine which method is being called at a particular location. +The second case is *polyvariant references*. +Consider the case of a JavaScript program. +JavaScript is a dynamically typed language, so the IDE cannot always precisely determine which method is being called at a particular location. To handle this, it provides a reference that can be resolved to multiple possible elements. Such references implement the [`PsiPolyVariantReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiPolyVariantReference.java) interface. -For resolving a `PsiPolyVariantReference`, you call its `multiResolve()` method. The call returns an array of -[`ResolveResult`](upsource:///platform/core-api/src/com/intellij/psi/ResolveResult.java) objects. Each of the -objects identifies a PSI element and also specifies whether the result is valid. For example, if you have multiple -Java method overloads and a call with arguments not matching any of the overloads, you will get -back `ResolveResult` objects for all of the overloads, and `isValidResult()` returns `false` for all of them. +For resolving a `PsiPolyVariantReference`, you call its `multiResolve()` method. +The call returns an array of [`ResolveResult`](upsource:///platform/core-api/src/com/intellij/psi/ResolveResult.java) objects. +Each of the objects identifies a PSI element and also specifies whether the result is valid. +For example, suppose you have multiple Java method overloads and a call with arguments not matching any of the overloads. In that case, you will get back `ResolveResult` objects for all of the overloads, and `isValidResult()` returns `false` for all of them. ## Searching for References -As you already know, resolving a reference means going from usage to the corresponding declaration. To perform the -navigation in the opposite direction - from a declaration to its usages - perform a **references search**. +As you already know, resolving a reference means going from usage to the corresponding declaration. +To perform the navigation in the opposite direction - from a declaration to its usages - perform a **references search**. -To perform a search using [`ReferencesSearch`](upsource:///platform/indexing-api/src/com/intellij/psi/search/searches/ReferencesSearch.java), specify the *element* to search for, and optionally other parameters such as the -scope in which the reference needs to be searched. The created [`Query`](upsource:///platform/core-api/src/com/intellij/util/Query.java) allows obtaining all results -at once or iterating over the results one by one. The latter allows stopping processing as soon as the first (matching) result has been found. +To perform a search using [`ReferencesSearch`](upsource:///platform/indexing-api/src/com/intellij/psi/search/searches/ReferencesSearch.java), specify the *element* to search for, and optionally other parameters such as the scope in which the reference needs to be searched. +The created [`Query`](upsource:///platform/core-api/src/com/intellij/util/Query.java) allows obtaining all results at once or iterating over the results one by one. +The latter allows stopping processing as soon as the first (matching) result has been found. ## Implementing References -Please refer to the [guide](/reference_guide/custom_language_support/references_and_resolve.md) and -corresponding [tutorial](/tutorials/custom_language_support/reference_contributor.md) for more information. +Please refer to the [guide](/reference_guide/custom_language_support/references_and_resolve.md) and corresponding [tutorial](/tutorials/custom_language_support/reference_contributor.md) for more information. diff --git a/basics/architectural_overview/virtual_file.md b/basics/architectural_overview/virtual_file.md index 54354e922..f0d435d76 100644 --- a/basics/architectural_overview/virtual_file.md +++ b/basics/architectural_overview/virtual_file.md @@ -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). -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. -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? From an action : `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()` - `VirtualFileManager.findFileByNioPath()`/`refreshAndFindFileByNioPath()` (2020.2 and later) @@ -27,7 +28,7 @@ From a document ## 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. ## 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? -A particular file on disk is represented by equal `VirtualFile` instances for the entire lifetime of the IDE process. -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. +A particular file on disk is represented by equal `VirtualFile` instances for the IDE process's entire lifetime. +There may be several instances corresponding to the same file, and they can be garbage-collected. +The file is a `UserDataHolder`, and the user data is shared between those equal instances. If a file is deleted, its corresponding VirtualFile instance becomes invalid (`isValid()` returns `false`), and operations cause exceptions. ## How do I create a virtual file? -Usually, you don't. As a general rule, files are created either through the PSI API or through the regular `java.io.File` API. +Usually, you don't. +As a general rule, files are created either through the PSI API or through the regular `java.io.File` API. If one needs to create a file through VFS, use `VirtualFile.createChildData()` to create a `VirtualFile` instance and `VirtualFile.setBinaryContent()` to write some data to the file. @@ -56,7 +58,8 @@ If one needs to create a file through VFS, use `VirtualFile.createChildData()` t > **NOTE** See [Virtual file system events](/basics/virtual_file_system.md#virtual-file-system-events) for important details. -Implement [`BulkFileListener`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/newvfs/BulkFileListener.java) and subscribe to the [message bus](/reference_guide/messaging_infrastructure.md) topic `VirtualFileManager.VFS_CHANGES`. For example: +Implement [`BulkFileListener`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/newvfs/BulkFileListener.java) and subscribe to the [message bus](/reference_guide/messaging_infrastructure.md) topic `VirtualFileManager.VFS_CHANGES`. +For example: ```java project.getMessageBus().connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { diff --git a/basics/disposers.md b/basics/disposers.md index 11bf23360..11490daf7 100644 --- a/basics/disposers.md +++ b/basics/disposers.md @@ -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. The most common resource type managed by `Disposer` is listeners, but there are other possible types: -* File handles, and database connections, -* Caches and other significant data structures. +* File handles, and database connections, +* 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. 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 -A number of objects are disposed automatically by the platform if they implement the `Disposable` interface. -The most important type of such objects is [services](/basics/plugin_structure/plugin_services.md). Application-level -services are automatically disposed by the platform when the IDE is closed, or the plugin providing the service is -unloaded. Project-level services are disposed when the project is closed or the plugin is unloaded. +Many objects are disposed automatically by the platform if they implement the `Disposable` interface. +The most important type of such objects is [services](/basics/plugin_structure/plugin_services.md). +Application-level services are automatically disposed by the platform when the IDE is closed or the plugin providing the service is unloaded. +Project-level services are disposed when the project is closed, or the plugin is unloaded. -Note that extensions registered in `plugin.xml` are *not* automatically disposed. If an extension requires executing -some code to dispose it, you need to define a service and to put the code in its `dispose()` method or use it as a parent -disposable. +Note that extensions registered in `plugin.xml` are *not* automatically disposed. +If an extension requires executing some code to dispose it, you need to define a service and to put the code in its `dispose()` method or use it as a parent disposable. ## The Disposer Singleton -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 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. @@ -42,7 +41,7 @@ Registering a disposable is performed by calling `Disposer.register()`: ```java Disposer.register(parentDisposable, childDisposable); ``` - + ### Choosing a Disposable Parent 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: -* For resources required for the entire lifetime of a plugin, use an application or project level [service](/basics/plugin_structure/plugin_services.md). +* For resources required for a plugin's entire lifetime, use an application or project level [service](/basics/plugin_structure/plugin_services.md). * For resources required while a [dialog](/user_interface_components/dialog_wrapper.md) is displayed, use `DialogWrapper.getDisposable()`. * For resources required while a [tool window](/user_interface_components/tool_windows.md) tab is displayed, pass your instance implementing `Disposable` to `Content.setDisposer()`. -* For resources with a shorter lifetime, create a disposable using `Disposer.newDisposable()` and dispose it manually -using `Disposable.dispose()`. Note that it's always best to specify a parent for such a disposable (e.g., a project-level service), -so that there is no memory leak if the `Disposable.dispose()` call is not reached because of an exception or a programming error. +* For resources with a shorter lifetime, create a disposable using `Disposer.newDisposable()` and dispose it manually using `Disposable.dispose()`. + Note that it's always best to specify a parent for such a disposable (e.g., a project-level service), so that there is no memory leak if the `Disposable.dispose()` call is not reached because of an exception or a programming error. > **WARNING** Even though `Application` and `Project` implement `Disposable`, they must NEVER be used as parent disposables in plugin code. Disposables registered using those objects as parents will not be disposed when the plugin is unloaded, leading to memory leaks. -The flexibility of the `Disposer` API means that if the parent instance is chosen unwisely, the child may consume resources for longer than required. -Continuing to use resources when they are no longer needed can be a severe source of contention due to leaving some zombie objects behind as a result of each invocation. +The `Disposer` API's flexibility means that if the parent instance is chosen unwisely, the child may consume resources for longer than required. +Continuing to use resources when they are no longer needed can be a severe source of contention due to leaving some zombie objects behind due to each invocation. An additional challenge is that these kinds of issues won't be reported by the regular leak checker utilities, because technically, it's not a memory leak from the test suite perspective. -For example, if a UI component created for a specific operation uses a project-level service as a parent disposable, -the entire component will remain in memory after the operation is complete. This creates memory pressure and can waste -CPU cycles on processing events that are no longer relevant for anything. +For example, suppose a UI component created for a specific operation uses a project-level service as a parent disposable. In that case, the entire component will remain in memory after the operation is complete. +This creates memory pressure and can waste CPU cycles on processing events that are no longer relevant. ### Registering Listeners with Parent Disposable -Many IntelliJ Platform APIs for registering listeners either require passing a parent disposable or have overloads that -take a parent disposable. For example: +Many IntelliJ Platform APIs for registering listeners either require passing a parent disposable or have overloads that take a parent disposable. +For example: ```java public abstract class EditorFactory { @@ -82,39 +79,38 @@ public abstract class EditorFactory { } ``` -Methods with a `parentDisposable` parameter automatically unsubscribe the listener when the corresponding parent disposable -is disposed. Using such methods is always preferable to removing listeners explicitly from the `dispose` method, because -it requires less code and is easier to verify for correctness. +Methods with a `parentDisposable` parameter automatically unsubscribe the listener when the corresponding parent disposable is disposed. +Using such methods is always preferable to removing listeners explicitly from the `dispose` method because it requires less code and is easier to verify for correctness. To choose the correct parent disposable, use the guidelines from the previous section. -The same rules apply to [message bus](/reference_guide/messaging_infrastructure.md) connections. Always pass a parent disposable to `MessageBus.connect()`, and make sure -it has the shortest possible lifetime. +The same rules apply to [message bus](/reference_guide/messaging_infrastructure.md) connections. +Always pass a parent disposable to `MessageBus.connect()`, and make sure it has the shortest possible lifetime. ### Determining Disposal Status -You can use `Disposer.isDisposed()` to check whether a `Disposable` has already been disposed. +You can use `Disposer.isDisposed()` to check whether a `Disposable` has already been disposed. This check is useful, for example, for an asynchronous callback to a `Disposable` that may be disposed before the callback is executed. In such a case, the best strategy is usually to do nothing and return early. -> **WARNING** Non-disposed objects shouldn't hold onto references to disposed objects, as this constitutes a memory leak. Once a `Disposable` is released, it should be completely inactive, and there's no reason to refer to it anymore. +> **WARNING** Non-disposed objects shouldn't hold onto references to disposed objects, as this constitutes a memory leak. +> Once a `Disposable` is released, it should be completely inactive, and there's no reason to refer to it anymore. ### Ending a Disposable Lifecycle -A plugin can manually end a `Disposable` lifecycle by calling `Disposer.dispose(Disposable)`. +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. ## Implementing the Disposable Interface Creating a class requires implementing the `Disposable` interface and defining the `dispose()` method. -In many cases, when the object implements `Disposable` only to be used as a parent disposable, the implementation of the -method will be completely empty. +In many cases, when the object implements `Disposable` only to be used as a parent disposable, the method's implementation will be completely empty. An example of a non-trivial `dispose` implementation is shown below: ```java public class Foo extends JBFoo implements Disposable { 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); } @@ -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 `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 -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. 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. -That code, in turn, allocated a `Project` that was never disposed by the time the application exited. -That is a promising initial place to start digging. +In turn, that code allocated a `Project` that was never disposed by the time the application exited. +That is a promising place to start digging. -The above memory leak was ultimately caused by failing to pass a `Project` instance to a function responsible for registering it for disposal. -Often the fix for a memory leak is as simple as understanding the memory scope of the object being allocated - often a UI container, project, or application - and making sure a `Disposer.register()` call is made appropriately for it. +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 - usually a UI container, project, or application - and making sure a `Disposer.register()` call is made appropriately for it. diff --git a/basics/faq.md b/basics/faq.md index f97210017..31da53eec 100644 --- a/basics/faq.md +++ b/basics/faq.md @@ -5,8 +5,7 @@ redirect_from: --- -This FAQ is a topical index of questions that have been asked (and answered) on our -[IntelliJ IDEA Open API and Plugin Development forum](https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development). +This FAQ is a topical index of questions that have been asked (and answered) on our [IntelliJ IDEA Open API and Plugin Development forum](https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development). ## Open-Source Plugins * [How do I compile the Scala plugin?](https://github.com/jetbrains/intellij-scala#setting-up-the-project) @@ -19,7 +18,7 @@ This FAQ is a topical index of questions that have been asked (and answered) on * [How do I add a main menu item?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206750335-Add-new-Main-menu-option-for-plugin) * [How do I customize the "New..." menu?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206765055-Overriding-the-New-context-menu-in-the-Project-view) * [How do I customize the compiler output context menu?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206142169-How-to-add-a-menu-item-below-Exclude-From-Compile-) -* [How do I get the context of an action (selected file, active project etc.)?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206756455-Question-about-Actions) +* [How do I get the context of an action (selected file, active project, etc.)?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206756455-Question-about-Actions) * [How do I change the icon of an action dynamically?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206763405-How-to-dynamically-change-icons-in-the-tool-bar-) * [How do I add icons to the IDEA toolbar?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206151289-How-to-add-icons-to-the-toolbar-) * [Where do I get the list of built-in action IDs?](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206126699-List-of-built-in-action-ID-s-) diff --git a/basics/getting_started.md b/basics/getting_started.md index afae50768..81c2a0bb2 100644 --- a/basics/getting_started.md +++ b/basics/getting_started.md @@ -3,13 +3,16 @@ title: Creating Your First Plugin --- -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 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: * 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), * Changing the target IntelliJ Platform-based IDE, e.g., from IntelliJ IDEA to PyCharm, * 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). ## Using GitHub Template diff --git a/basics/getting_started/build_number_ranges.md b/basics/getting_started/build_number_ranges.md index b9a889b9b..6e999cb41 100644 --- a/basics/getting_started/build_number_ranges.md +++ b/basics/getting_started/build_number_ranges.md @@ -1,6 +1,7 @@ --- title: Build Number Ranges --- + ## Introduction -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. -Underlying those shared features are shared components. +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. +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. 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. * bullet list {:toc} ## 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. -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. +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. +Declaring a dependency on a module also expresses a plugin's compatibility with a product in that the IntelliJ Platform determines whether a product contains the correct modules to support a plugin before loading it. -[Part I](/basics/plugin_structure/plugin_dependencies.md) of this document describes the syntax for declaring plugin dependencies and optional plugin dependencies. -Part II of this document (below) describes the functionality of the IntelliJ Platform modules to aid in determining the dependencies of a plugin. +[Part 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 IntelliJ Platform modules' functionality to aid in determining the dependencies of a plugin. The way dependency declarations are handled by the Intellij Platform is determined by the contents of the `plugin.xml` file: * If a plugin does not declare any dependencies in its `plugin.xml` file, or if it declares dependencies only on other plugins but not modules, it's assumed to be a legacy plugin and is loaded only in IntelliJ IDEA. - This configuration of dependency declaration is deprecated; do not use it for new plugin projects. + This configuration of the dependency declaration is deprecated; do not use it for new plugin projects. * If a plugin declares at least _one_ module dependency in its `plugin.xml` file, the plugin is loaded if an IntelliJ Platform-based product contains _all the modules and plugins_ on which the plugin has declared a dependency. ## Modules -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. +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. This section identifies and discusses modules of both types. ### Declaring Incompatibility with Module Starting in 2020.2, a plugin can declare incompatibility with an arbitrary module by specifying `` containing module ID in its `plugin.xml`. ### Modules Available in All Products -A core set of modules are available in all products based on the IntelliJ Platform. -These modules provide a set of shared functionality. -The following table lists modules that are currently available in all products. - -> **NOTE** All plugins should declare a dependency on **`com.intellij.modules.platform`** as an indication of dependence on shared functionality. +A core set of modules are available in all products based on the IntelliJ Platform. +These modules provide a set of shared functionality. +The following table lists modules that are currently available in all products. -| Module for `` Element
Declaration in `plugin.xml` File |
Functionality | +> **NOTE** All plugins should declare a dependency on **`com.intellij.modules.platform`** to indicate dependence on shared functionality. + +| Module for `` Element
Declaration in `plugin.xml` File |
Functionality | |--------------------------------------|----------------------------------------------------------------------------------------------------------------| | **`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 | @@ -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. ### Modules Specific to Functionality -More specialized functionality is also delivered via modules and plugins in IntelliJ Platform-based products. -For example, the `com.intellij.modules.python` module supports the Python language-specific functionality. -If a plugin uses functionality from this module, such as Python-specific inspections and refactoring, it must declare a dependency on this module. +More specialized functionality is also delivered via modules and plugins in IntelliJ Platform-based products. +For example, the `com.intellij.modules.python` module supports the Python language-specific functionality. +If a plugin uses 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. 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 `` Element
Declaration in `plugin.xml` File |
Functionality | IntelliJ Platform-Based
Product Compatibility | +| Module or Plugin for `` Element
Declaration in `plugin.xml` File |
Functionality | IntelliJ Platform-Based
Product Compatibility | |------------------------------------------------------------------------------|--------------------|------------------------------------------| | `com.intellij.modules.java` See (2) below.
`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 | @@ -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. | | `JavaScript` | **JavaScript** language PSI Model, Inspections, Intentions, Completion, Refactoring, Test Framework | WebStorm, and other products if the JavaScript plugin is installed. | -**Notes about Module and Plugin Dependency:** -**(1)** This table is not exhaustive, there are other modules currently available in JetBrains' IntelliJ Platform-based IDEs. +**Notes about Module and Plugin Dependency:** +**(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 `` 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. -This refactoring separated the Java implementation from the other, non-language portions of the 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. 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 `com.intellij.modules.java` * Syntax for 2019.2 and later releases: * `plugin.xml` _allowable_ alternative include `com.intellij.java` - * `build.gradle` _required_ to include `intellij { plugins 'java' }` + * `build.gradle` _required_ to include `intellij { plugins 'java' }` ## 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. @@ -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. 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 `` 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). +Look for the library `Gradle:unzipped.com.jetbrains.plugins:foo:`, where "foo" matches, or is similar to the contents of the `` tags in `plugin.xml` or the `intellij.plugins` declaration in `build.gradle`. +The image below shows the External Libraries for the example plugin project configuration explained in [Configuring build.gradle](/products/dev_alternate_products.md#configuring-buildgradle-using-the-intellij-idea-product-attribute) and [Configuring plugin.xml](/products/dev_alternate_products.md#configuring-pluginxml). ![Example PhpStorm Project Libraries](img/php_prj_libs.png){:width="700px"} @@ -124,7 +124,7 @@ Expand the External Library (as shown) to reveal the JAR files contained in the Drill down into the JAR files to expose the packages and (decompiled) classes. ### Exploring APIs as an Extender -If a project is dependent on a plugin or module, in some cases the project can also [extend](/basics/plugin_structure/plugin_extensions.md) the functionality available from the plugin or module. +If a project is dependent on a plugin or module, in some cases, the project can also [extend](/basics/plugin_structure/plugin_extensions.md) the functionality available from the plugin or module. To browse the opportunities for extension, start by placing the cursor on the contents of the `` 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. @@ -138,17 +138,16 @@ Continuing the example, search the PHP plugin's `plugin.xml` file for: ## 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 [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. +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. -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. +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. ## 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. - diff --git a/basics/getting_started/publishing_plugin.md b/basics/getting_started/publishing_plugin.md index 807b5ea40..9cb98e6e7 100644 --- a/basics/getting_started/publishing_plugin.md +++ b/basics/getting_started/publishing_plugin.md @@ -3,15 +3,13 @@ title: Publishing a Plugin --- -When your plugin is ready, you can publish it to a plugin repository so that other users can install it. -You can choose to publish it on the [JetBrains Plugins Repository](https://plugins.jetbrains.com) -or a [custom plugin repository](/basics/getting_started/update_plugins_format.md). +When your plugin is ready, you can publish it to a plugin repository so that other users can install it. +You can choose to publish it on the [JetBrains Plugins Repository](https://plugins.jetbrains.com) or a [custom plugin repository](/basics/getting_started/update_plugins_format.md). > **TIP** Please see [Marketing](/appendix/resources/marketing.md) for remarks on how to prepare your plugin for optimal presentation. ### Publishing to the JetBrains Plugins Repository -To upload your plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com), -you must log in with your personal JetBrains Account. +To upload your plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com), you must log in with your personal JetBrains Account. **To get your JetBrains account:** @@ -20,10 +18,9 @@ you must log in with your personal JetBrains Account. **To upload your plugin to JetBrains Plugins Repository:** -1. [Login to JetBrains Plugins Repository](https://plugins.jetbrains.com/author/me) with your personal JetBrains account. +1. [Log in to JetBrains Plugins Repository](https://plugins.jetbrains.com/author/me) with your personal JetBrains account. 2. On your Profile page that opens, click **Add new plugin**. 3. Fill in the **Add new plugin** form that opens and click the **Add the plugin** button to upload your plugin. ### Publishing a Plugin to a Custom Plugin Repository -If you plan to publish your plugin to a repository _other than_ the [JetBrains Plugins Repository](https://plugins.jetbrains.com), -please refer to the [Publishing to Custom Plugin Repositories](update_plugins_format.md) documentation. +If you plan to publish your plugin to a repository _other than_ the [JetBrains Plugins Repository](https://plugins.jetbrains.com), please refer to the [Publishing to Custom Plugin Repositories](update_plugins_format.md) documentation. diff --git a/basics/getting_started/running_and_debugging_a_plugin.md b/basics/getting_started/running_and_debugging_a_plugin.md index 934bbd746..beaeaffac 100644 --- a/basics/getting_started/running_and_debugging_a_plugin.md +++ b/basics/getting_started/running_and_debugging_a_plugin.md @@ -3,7 +3,8 @@ title: Running and Debugging a Plugin --- -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. diff --git a/basics/getting_started/setting_up_environment.md b/basics/getting_started/setting_up_environment.md index ca1768a9d..467694601 100644 --- a/basics/getting_started/setting_up_environment.md +++ b/basics/getting_started/setting_up_environment.md @@ -9,46 +9,46 @@ title: Setting Up a Development Environment Use the following checklist to ensure that you are ready to develop your custom plugins. -- **Get IntelliJ IDEA CE source code** on your local computer. Getting IntelliJ IDEA CE source code is not a requirement for plugin development, but having it makes debugging your plugins much more straightforward. For detailed instructions, refer to the _Getting IntelliJ IDEA Community Edition Source Code_ section of [Check Out And Build Community Edition](upsource:///README.md). Note that building IntelliJ IDEA CE from source code is not required for plugin development. +- **Get IntelliJ IDEA CE source code** on your local computer. + Getting IntelliJ IDEA CE source code is not a requirement for plugin development, but having it makes debugging your plugins much more straightforward. + For detailed instructions, refer to the _Getting IntelliJ IDEA Community Edition Source Code_ section of [Check Out And Build Community Edition](upsource:///README.md). + Note that building IntelliJ IDEA CE from source code is not required for plugin development. - **Plugin DevKit** plugin must be [enabled in IntelliJ IDEA](https://www.jetbrains.com/help/idea/managing-plugins.html). -- **IntelliJ Platform SDK** must be configured for your IDEA project. For more information, see below. - +- **IntelliJ Platform SDK** must be configured for your IDEA project. + For more information, see below. + ### Configuring IntelliJ Platform SDK - + To set up your plugin development environment: -* Create a new *IntelliJ Platform SDK* under **File \| Project Structure**: +* Create a new *IntelliJ Platform SDK* under **File \| Project Structure**: + ![Create IntelliJ Platform SDK](img/create_intellij_idea_sdk.png) +
+
+* 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*. + ![Set Home Directory](img/set_home_directory.png) +
+
+* Select **1.8** as the default Java SDK. + See the _IntelliJ Build Configuration_ section of [Check Out And Build Community Edition](upsource:///README.md) for instructions about creating **1.8** Java SDK. + ![Set IDEA JDK](img/set_java_sdk.png) +
+
+* In the Sourcepath tab of the SDK settings, click the *Add* button: + ![Add Sourcepath](img/add_sourcepath.png) +
+
+* Specify the source code directory for the *IntelliJ IDEA Community Edition*: + ![Specify Source Paths](img/community_sources_directory.png) +
+
+* 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. - ![Create IntelliJ Platform SDK](img/create_intellij_idea_sdk.png) -
-
-* 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*. - - ![Set Home Directory](img/set_home_directory.png) -
-
-* Select **1.8** as the default Java SDK. See the _IntelliJ Build Configuration_ section of [Check Out And Build Community Edition](upsource:///README.md) for instructions about creating **1.8** Java SDK. - - ![Set IDEA JDK](img/set_java_sdk.png) -
-
-* In the Sourcepath tab of the SDK settings, click the *Add* button: - - ![Add Sourcepath](img/add_sourcepath.png) -
-
-* Specify the source code directory for the *IntelliJ IDEA Community Edition*: - - ![Specify Source Paths](img/community_sources_directory.png) -
-
-* 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. + See the [IDE Development Instances](/basics/ide_development_instance.md) page for more information about default *Sandbox Home* directory locations and contents. - ![Specify Sandbox Path](img/plugins-sandbox.png) + ![Specify Sandbox Path](img/plugins-sandbox.png) diff --git a/basics/getting_started/update_plugins_format.md b/basics/getting_started/update_plugins_format.md index 6fd9b5c42..feac46a6f 100644 --- a/basics/getting_started/update_plugins_format.md +++ b/basics/getting_started/update_plugins_format.md @@ -3,36 +3,34 @@ title: Publishing a Plugin to a Custom Plugin Repository --- -If you intend to use a plugin repository _other than_ the [JetBrains Plugins Repository](https://plugins.jetbrains.com), -you will need to: -* Create and maintain an `updatePlugins.xml` file on the HTTPS web server you are using for your custom repository. +If you intend to use a plugin repository _other than_ the [JetBrains Plugins Repository](https://plugins.jetbrains.com), you will need to: +* Create and maintain an `updatePlugins.xml` file on the HTTPS web server you are using for your custom repository. This file describes all the plugins available in your custom repository and each plugin's download URL. -* Upload your plugin JAR/ZIP file to an HTTPS web server. This can be the same web server you are using for the custom repository - or a different HTTPS web server. +* Upload your plugin JAR/ZIP file to an HTTPS web server. + This can be the same web server you are using for the custom repository or a different HTTPS web server. * Add the URL for the custom repository to the JetBrains IDE [Repository Settings/Preferences](https://www.jetbrains.com/help/idea/managing-plugins.html#repos). ## Describing Your Plugins in updatePlugins.xml File -Every custom plugin repository must have at least one `updatePlugins.xml` file to describe the latest available version -for every hosted plugin. The description in `updatePlugins.xml` is used by JetBrains IDEs to locate plugins by attributes -such as id, IDE version, and plugin version. These attributes are displayed by JetBrains IDEs to help users select or upgrade plugins. +Every custom plugin repository must have at least one `updatePlugins.xml` file to describe every hosted plugin's latest available version. +The description in `updatePlugins.xml` is used by JetBrains IDEs to locate plugins by attributes such as id, IDE version, and plugin version. +These attributes are displayed by JetBrains IDEs to help users select or upgrade plugins. The description also tells the JetBrains IDE where to download the plugin itself. -A custom plugin repository's `updatePlugins.xml` file is constructed and maintained by the administrator of -the repository. More than one `updatePlugins.xml` file may be required if consumers of the custom repository are using more -than one version of a JetBrains IDE. For example `updatePlugins-182.xml`, `updatePlugins-183.xml` for IntelliJ IDEA 2018.2 and 2018.3 respectively. -Each `updatePlugins-*.xml` file will have a unique URL that is added to the JetBrains IDE -[Repository Settings/Preferences](https://www.jetbrains.com/help/idea/managing-plugins.html#repos). +A custom plugin repository's `updatePlugins.xml` file is constructed and maintained by the repository administrator. +More than one `updatePlugins.xml` file may be required if the custom repository consumers are using more than one version of a JetBrains IDE. +For example, `updatePlugins-182.xml`, `updatePlugins-183.xml` for IntelliJ IDEA 2018.2 and 2018.3, respectively. +Each `updatePlugins-*.xml` file will have a unique URL that is added to the JetBrains IDE [Repository Settings/Preferences](https://www.jetbrains.com/help/idea/managing-plugins.html#repos). ### Format of updatePlugins.xml File The format of an `updatePlugins.xml` file is simply a list of sequential elements that describe each plugin: ```xml - - -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. 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. ## Using a JetBrains Runtime for the Development Instance -A common use case is to develop (build) a plugin project against a JDK, e.g., Java 8, and then run or debug the plugin in a Development Instance of the IDE. +An everyday use case is to develop (build) a plugin project against a JDK, e.g., Java 8, and then run or debug the plugin in a Development Instance of the IDE. In such a situation, Development Instance must use a JetBrains Runtime (JBR) rather than the JDK used to build the plugin project. -The JetBrains Runtime is an environment for running IntelliJ Platform-based IDEs on Windows, macOS, and Linux. +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. 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. ### Determining a JetBrains Runtime Version -The JetBrains Runtime is determined from the JDK version used to build the plugin project. -If a plugin is being developed against the Java 8 SE Development Kit 8 for macOS, for example, `jdk-8u212-macosx-x64.dmg`. -(This example will use macOS, but Windows and Linux follow the same procedure.) -To acquire the compatible JetBrains Runtime: +The JetBrains Runtime is determined from the JDK version used to build the plugin project, regardless of whether it is built on macOS, Windows, or Linux. +For example, if a plugin is developed against the Java 8 SE Development Kit 8 for macOS (`jdk-8u212-macosx-x64.dmg`) to acquire the compatible JetBrains Runtime: + * Go to the [JetBrains Runtime Site](https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime) for general information and the latest build. * Open the [Release notes](https://confluence.jetbrains.com/display/JBR/Release+notes) page to access all releases. * Select the package name corresponding to the platform and SDK version. @@ -34,7 +33,7 @@ To acquire the compatible JetBrains Runtime: * The version and build number match the JDK used to build the plugin project. For example, `jbrx-8u252-osx-x64` matches the Java 8 JDK, build 252: `jdk-8u252-macosx-x64`. * Pick the highest JetBrains Runtime build number available. - For example, as of this writing, the file is `jbrx-8u252-osx-x64-b1649.2.tar.gz`, meaning build 1649.2 for this JetBrains Runtime matching Java 8 JDK build 252. + For example, the file is `jbrx-8u252-osx-x64-b1649.2.tar.gz`, meaning build 1649.2 for this JetBrains Runtime matching Java 8 JDK build 252. ### Setting a JetBrains Runtime for Gradle-Based Plugin Projects By default, the Gradle plugin will fetch and use the version of the JetBrains Runtime for the Development Instance corresponding to the version of the IntelliJ Platform used for building the plugin project. @@ -43,7 +42,7 @@ If required, an alternative version can be specified using `jbrVersion` attribut ### Setting a JetBrains Runtime for DevKit-Based Plugin Projects The [Run Configuration](https://www.jetbrains.com/help/idea/run-debug-configuration.html) for a DevKit-based plugin project controls the JDK used to run and debug a plugin project in a Development Instance. The default Run Configuration uses the same JDK for building the plugin project and running the plugin in a Development Instance. -To change the runtime for the Development Instance, set the _JRE_ field in the Run Configuration edit dialog to use a downloaded JetBrains Runtime. +To change the runtime for the Development Instance, set the _JRE_ field in the Run Configuration edit dialog to download a JetBrains Runtime. ## Enabling Auto-Reload @@ -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. 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). 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+). -## 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 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. 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 -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. +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. The default Sandbox Home location for Gradle-based plugin projects is: * **Windows** `\build\idea-sandbox` * **Linux or macOS** `/build/idea-sandbox` ### 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. -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:** `\.\system\plugins-sandbox\` * **Linux:** `~/./system/plugins-sandbox/` * **macOS** `~/Library/Caches//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 Within the Sandbox Home directory are subdirectories of the Development 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/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. diff --git a/basics/indexing_and_psi_stubs.md b/basics/indexing_and_psi_stubs.md index 944917a20..cee5dac56 100644 --- a/basics/indexing_and_psi_stubs.md +++ b/basics/indexing_and_psi_stubs.md @@ -5,32 +5,43 @@ title: Indexing and PSI Stubs ## Indices -The indexing framework provides a quick way to locate certain elements, e.g. files containing a certain word or methods with a particular name, in large code bases. Plugin developers can use the existing indexes built by the IDE itself, as well as build and use their own indexes. +The indexing framework provides a quick way to locate specific elements, e.g., files containing a certain word or methods with a particular name, in large codebases. +Plugin developers can use the existing indexes built by the IDE itself and build and use their own indexes. It supports two main types of indexes: * [File-based indices](/basics/indexing_and_psi_stubs/file_based_indexes.md) * [Stub indices](/basics/indexing_and_psi_stubs/stub_indexes.md) -File-based indexes are built directly over the content of files. Stub indexes are built over serialized *stub trees*. A stub tree for a source file is a subset of its PSI tree which contains only externally visible declarations and is serialized in a compact binary format. +File-based indexes are built directly over the content of files. +Stub indexes are built over serialized *stub trees*. +A stub tree for a source file is a subset of its PSI tree, which contains only externally visible declarations and is serialized in a compact binary format. -Querying a file-based index gets you the set of files matching a certain condition. Querying a stub index gets you the set of matching PSI elements. Therefore, custom language plugin developers should typically use stub indexes in their plugin implementations. +Querying a file-based index gets you the set of files matching a specific condition. +Querying a stub index gets you the set of matching PSI elements. +Therefore, custom language plugin developers should typically use stub indexes in their plugin implementations. -> **TIP** [Indices Viewer](https://plugins.jetbrains.com/plugin/13029-indices-viewer/) is a plugin that helps inspecting indices' contents and properties. +> **TIP** [Indices Viewer](https://plugins.jetbrains.com/plugin/13029-indices-viewer/) is a plugin that helps to inspect indices' contents and properties. Please see also [Improving indexing performance](/reference_guide/performance/performance.md#improving-indexing-performance). ## Dumb Mode -Indexing is a potentially long process. It's performed in background, and during this time, IDE's features are restricted to the ones that don't require index: basic text editing, version control etc. This restriction is managed by [`DumbService`](upsource:///platform/core-api/src/com/intellij/openapi/project/DumbService.java). +Indexing is a potentially lengthy process. +It's performed in the background, and during this time, IDE's features are restricted to the ones that don't require index: basic text editing, version control, etc. +This restriction is managed by [`DumbService`](upsource:///platform/core-api/src/com/intellij/openapi/project/DumbService.java). -`DumbService` provides API to query whether the IDE is currently in "dumb" mode (where index access is not allowed) or "smart" mode (with all index built and ready to use). It also provides ways of delaying code execution until indices are ready. Please see its javadoc for more details. +`DumbService` provides API to query whether the IDE is currently in "dumb" mode (where index access is not allowed) or "smart" mode (with all index built and ready to use). +It also provides ways of delaying code execution until indices are ready. +Please see its JavaDoc for more details. ## Gists Sometimes, the following conditions hold: -* the aggregation functionality of file-based indices is not needed. One just needs to calculate some data based on particular file's contents, and cache it on disk -* eagerly calculating the data for the entire project during indexing isn't needed (e.g. it slows down the indexing, and/or this data probably will ever be needed for a minor subset of all project files) -* the data can be recalculated lazily on request without major performance penalties +* the aggregation functionality of file-based indices is not needed. + One just needs to calculate some data based on a particular file's contents and cache it on disk. +* eagerly calculating the data for the entire project during indexing isn't needed (e.g., it slows down the indexing, and/or this data probably will ever be required for a minor subset of all project files). +* the data can be recalculated lazily on request without significant performance penalties. -In such cases, file-based index can be used, but file gists provide a way to perform data calculation lazily, caching on disk, and a more lightweight API. Please see [`VirtualFileGist`](upsource:///platform/indexing-api/src/com/intellij/util/gist/VirtualFileGist.java) and [`PsiFileGist`](upsource:///platform/indexing-api/src/com/intellij/util/gist/PsiFileGist.java) documentation. +A file-based index can be used in such cases, but file gists provide a way to perform data calculation lazily, caching on disk, and a more lightweight API. +Please see [`VirtualFileGist`](upsource:///platform/indexing-api/src/com/intellij/util/gist/VirtualFileGist.java) and [`PsiFileGist`](upsource:///platform/indexing-api/src/com/intellij/util/gist/PsiFileGist.java) documentation. diff --git a/basics/indexing_and_psi_stubs/file_based_indexes.md b/basics/indexing_and_psi_stubs/file_based_indexes.md index 1f529d1e6..e2b06d6b1 100644 --- a/basics/indexing_and_psi_stubs/file_based_indexes.md +++ b/basics/indexing_and_psi_stubs/file_based_indexes.md @@ -3,7 +3,8 @@ title: File-Based Indexes --- -File-based indexes are based on a Map/Reduce architecture. Each index has a specific type of key and a particular type of value. +File-based indexes are based on a Map/Reduce architecture. +Each index has a specific type of key and a particular type of value. The key is what's later used to retrieve data from the index. @@ -11,19 +12,21 @@ The key is what's later used to retrieve data from the index. The value is arbitrary data, which is associated with the key in the index. -*Example:* in the word index, the value is a mask indicating in which context the word occurs (code, string literal or comment). +*Example:* in the word index, the value is a mask indicating in which context the word occurs (code, string literal, or comment). In the simplest case, when we only need to know in what files some data is present, the value has type `Void` and is not stored in the index. -When the index implementation indexes a file, it receives the content of a file and returns a map from the keys found in the file to the associated values. +When the index implementation indexes a file, it receives a file's content and returns a map from the keys found in the file to the associated values. When you access the index, you specify the key you're interested in and get back the list of files in which the key occurs, and the value associated with each file. ## Implementing a File-Based Index -A relatively simple file-based index implementation is the [UI Designer bound forms index](upsource:///plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java). Refer to it as an example to understand this topic better. +A relatively simple file-based index implementation is the [UI Designer bound forms index](upsource:///plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java). +Refer to it as an example to understand this topic better. -Each specific index implementation is a class extending [`FileBasedIndexExtension`](upsource:///platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java). A file-based index should be registered in the `com.intellij.fileBasedIndex` extension point. +Each specific index implementation is a class extending [`FileBasedIndexExtension`](upsource:///platform/indexing-api/src/com/intellij/util/indexing/FileBasedIndexExtension.java). +A file-based index should be registered in the `com.intellij.fileBasedIndex` extension point. An implementation of a file-based index consists of the following main parts: @@ -33,11 +36,13 @@ An implementation of a file-based index consists of the following main parts: Probably the most commonly used [`KeyDescriptor`](upsource:///platform/util/src/com/intellij/util/io/KeyDescriptor.java) implementation is [`EnumeratorStringDescriptor`](upsource:///platform/util/src/com/intellij/util/io/EnumeratorStringDescriptor.java), which is designed for storing efficiently storing identifiers. * `getValueExternalizer()` returns the value serializer responsible for storing values in a serialized binary format. * `getInputFilter()` allows restricting the indexing only to a certain set of files. -* `getVersion()` returns the version of the index implementation. The index is automatically rebuilt if the current version differs from the version of the index implementation used to build the index. +* `getVersion()` returns the version of the index implementation. + The index is automatically rebuilt if the current version differs from the version of the index implementation used to build it. If you don't need to associate any value with the files (i.e., your value type is `Void`), you can simplify the implementation by using [`ScalarIndexExtension`](upsource:///platform/indexing-api/src/com/intellij/util/indexing/ScalarIndexExtension.java) as the base class. -> **WARNING** The data returned by `DataIndexer.map()` must depend only on input data passed to the method, and must not depend on any external files. Otherwise, your index will not be correctly updated when the external data changes, and you will have stale data in your index. +> **WARNING** The data returned by `DataIndexer.map()` must depend only on input data passed to the method, and must not depend on any external files. +> Otherwise, your index will not be correctly updated when the external data changes, and you will have stale data in your index. > **NOTE** Please see `com.intellij.util.indexing.DebugAssertions` on how to enable additional debugging assertions during development to assert correct index implementation. @@ -52,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. * `getValues()` allows to get all values associated with a specific key but not the files in which they were found. -* `getContainingFiles()` allows to collect all files in which a specific key was encountered. -* `processValues()` allows iterating though all files in which a specific key was encountered and accessing the associated values at the same time. +* `getContainingFiles()` allows collecting all files in which a particular key was encountered. +* `processValues()` allows iterating through all files in which a specific key was encountered and accessing the associated values simultaneously. -> **WARNING** Nested index access is forbidden as it might lead to a deadlock. Collect all necessary data from index A first, then process results while accessing index B. +> **WARNING** Nested index access is forbidden as it might lead to a deadlock. +> Collect all necessary data from index A first, then process results while accessing index B. ## Standard Indexes -The *IntelliJ Platform* contains several standard file-based indexes. The most useful indexes for plugin developers are: +The *IntelliJ Platform* contains several standard file-based indexes. +The most useful indexes for plugin developers are: ### Word Index - + 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 diff --git a/basics/indexing_and_psi_stubs/stub_indexes.md b/basics/indexing_and_psi_stubs/stub_indexes.md index 0a02c816c..efcda6bb9 100644 --- a/basics/indexing_and_psi_stubs/stub_indexes.md +++ b/basics/indexing_and_psi_stubs/stub_indexes.md @@ -5,48 +5,69 @@ title: Stub Indexes ## Stub Trees -A stub tree is a subset of the PSI tree for a file; it is stored in a compact serialized binary format. The PSI tree for a file can be backed either by the AST (built by parsing the text of the file) or by the stub tree deserialized from disk. Switching between the two is transparent. +A stub tree is a subset of the PSI tree for a file; it is stored in a compact serialized binary format. +The PSI tree for a file can be backed either by the AST (built by parsing the file) or by the stub tree deserialized from disk. +Switching between the two is transparent. -The stub tree contains only a subset of the nodes. Typically it contains only the nodes that are needed to resolve the declarations contained in this file from external files. Trying to access any node which is not part of the stub tree, or to perform any operation which cannot be satisfied by the stub tree, e.g. accessing the text of a PSI element, causes file parsing and switches the PSI to AST backing. +The stub tree contains only a subset of the nodes. +Typically, it contains only the nodes needed to resolve the declarations contained in this file from external files. +Trying to access any node that is not part of the stub tree or perform any operation that cannot be satisfied by the stub tree, e.g., accessing the text of a PSI element, causes file parsing to switch from the PSI to AST backing. -Each stub in the stub tree is simply a bean class with no behavior. A stub stores a subset of the state of the corresponding PSI element, like element's name, modifier flags like public or final, etc. The stub also holds a pointer to its parent in the tree and a list of its children stubs. +Each stub in the stub tree is simply a bean class with no behavior. +A stub stores a subset of the corresponding PSI element's state, like the element's name, modifier flags like public or final, etc. +The stub also holds a pointer to its parent in the tree and a list of its children's stubs. -To support stubs for your custom language, you first need to decide which of the elements of your PSI tree should be stored as stubs. Typically you need to have stubs for things like methods or fields, which are visible from other files. You usually don't need to have stubs for things like statements or local variables, which are not visible externally. +To support stubs for your custom language, you first need to decide which of your PSI tree elements should be stored as stubs. +Typically, you need to have stubs for things like methods or fields visible from other files. +You usually don't need to have stubs for things like statements or local variables, which are not visible externally. For each element type that you want to store in the stub tree, you need to perform the following steps: * Define an interface for the stub, derived from the [`StubElement`](upsource:///platform/core-api/src/com/intellij/psi/stubs/StubElement.java) interface ([example](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/PropertyStub.java)). * Provide an implementation for the interface ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyStubImpl.java)). -* Make sure that the interface for the PSI element extends [`StubBasedPsiElement`](upsource:///platform/core-api/src/com/intellij/psi/StubBasedPsiElement.java) parameterized by the type of the stub interface ([example](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/Property.java)). -* Make sure that the implementation class for the PSI element extends [`StubBasedPsiElementBase`](upsource:///platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java) parameterized by the type of the stub interface ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java)). Provide both a constructor that accepts an `ASTNode` and a constructor which accepts a stub. -* Create a class which implements `IStubElementType` and is parameterized with the stub interface and the actual PSI element interface ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertyStubElementType.java)). Implement the `createPsi()` and `createStub()` methods for creating PSI from a stub and vice versa. Implement the `serialize()` and `deserialize()` methods for storing the data in a binary stream. +* Make sure the interface for the PSI element extends [`StubBasedPsiElement`](upsource:///platform/core-api/src/com/intellij/psi/StubBasedPsiElement.java) parameterized by the type of the stub interface ([example](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/psi/Property.java)). +* Make sure the implementation class for the PSI element extends [`StubBasedPsiElementBase`](upsource:///platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java) parameterized by the type of the stub interface ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java)). + Provide both a constructor that accepts an `ASTNode` and a constructor that accepts a stub. +* Create a class that implements `IStubElementType` and is parameterized with the stub interface and the actual PSI element interface ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertyStubElementType.java)). + Implement the `createPsi()` and `createStub()` methods for creating PSI from a stub and vice versa. + Implement the `serialize()` and `deserialize()` methods for storing the data in a binary stream. * Use the class implementing `IStubElementType` as the element type constant when parsing ([example](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesElementTypes.java)). -* Make sure that all methods in the PSI element interface access the stub data rather than the PSI tree when appropriate ([example: `Property.getKey()` implementation](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java)). +* Make sure all methods in the PSI element interface access the stub data rather than the PSI tree when appropriate ([example: `Property.getKey()` implementation](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java)). The following steps need to be performed only once for each language that supports stubs: * Change the file element type for your language (the element type that you return from `ParserDefinition.getFileNodeType()`) to a class that extends [`IStubFileElementType`](upsource:///platform/core-impl/src/com/intellij/psi/tree/IStubFileElementType.java). * In your `plugin.xml`, define the `com.intellij.stubElementTypeHolder` extension and specify the interface which contains the `IElementType` constants used by your language's parser as well as `externalIdPrefix` if possible ([example](upsource:///plugins/properties/src/META-INF/plugin.xml)). -For serializing string data, e.g. element names, in stubs, we recommend to use `StubOutputStream.writeName()` and `StubInputStream.readName()` methods. These methods ensure that each unique identifier is stored only once in the data stream. This reduces the size of the serialized stub tree data. +For serializing string data, e.g. element names, in stubs, we recommend to use `StubOutputStream.writeName()` and `StubInputStream.readName()` methods. +These methods ensure that each unique identifier is stored only once in the data stream. +This reduces the size of the serialized stub tree data. -If you need to change the stored binary format for the stubs (for example, if you want to store some additional data or some new elements), make sure that you advance the stub version returned from `IStubFileElementType.getStubVersion()` for your language. This will cause the stubs and stub indices to be rebuilt, and will avoid mismatches between the stored data format and the code trying to load it. +If you need to change the stored binary format for the stubs (for example, if you want to store some additional data or some new elements), make sure you advance the stub version returned from `IStubFileElementType.getStubVersion()` for your language. +This will cause the stubs and stub indices to be rebuilt, and will avoid mismatches between the stored data format, and the code trying to load it. -By default, if a PSI element extends `StubBasedPsiElement`, all elements of that type will be stored in the stub tree. If you need more precise control over which elements are stored, override `IStubElementType.shouldCreateStub()` and return `false` for elements which should not be included in the stub tree. +By default, if a PSI element extends `StubBasedPsiElement`, all elements of that type will be stored in the stub tree. +If you need more precise control over which elements are stored, override `IStubElementType.shouldCreateStub()` and return `false` for elements that should not be included in the stub tree. > **NOTE** The exclusion is not recursive: if some elements of the element for which you returned false are also stub-based PSI elements, they will be included in the stub tree. -It's essential to make sure that all information stored in the stub tree depends only on the contents of the file for which stubs are being built, and does not depend on any external files. Otherwise the stub tree will not be rebuilt when an external dependency changes, and you will have stale and incorrect data in the stub tree. +It's essential to ensure that all information stored in the stub tree depends only on the contents of the file for which stubs are being built, and does not depend on any external files. +Otherwise, the stub tree will not be rebuilt when external dependency changes, and you will have stale and incorrect data in the stub tree. > **TIP** Please see also [Improving indexing performance](/reference_guide/performance/performance.md#improving-indexing-performance). ## Stub Indexes -When building the stub tree, you can at the same time put some data about the stub elements into a number of indexes, which then can be used to find the PSI elements by the corresponding key. Unlike file-based indexes, stub indexes do not support storing custom data as values; the value is always a PSI element. Keys in stub indexes are normally strings (such as class names); other data types are also supported if desired. +When building the stub tree, you can, at the same time, put some data about the stub elements into a number of indexes, which then can be used to find the PSI elements by the corresponding key. +Unlike file-based indexes, stub indexes do not support storing custom data as values; the value is always a PSI element. +Keys in stub indexes are typically strings (such as class names); other data types are also supported if desired. -A stub index is a class which extends [`AbstractStubIndex`](upsource:///platform/indexing-api/src/com/intellij/psi/stubs/AbstractStubIndex.java). In the most common case, when the key type is `String`, you use a more specific base class, namely [`StringStubIndexExtension`](upsource:///platform/indexing-api/src/com/intellij/psi/stubs/StringStubIndexExtension.java). Stub index implementation classes are registered in the `com.intellij.stubIndex` extension point. +A stub index is a class which extends [`AbstractStubIndex`](upsource:///platform/indexing-api/src/com/intellij/psi/stubs/AbstractStubIndex.java). +In the most common case, when the key type is `String`, you use a more specific base class, namely [`StringStubIndexExtension`](upsource:///platform/indexing-api/src/com/intellij/psi/stubs/StringStubIndexExtension.java). +Stub index implementation classes are registered in the `com.intellij.stubIndex` extension point. -To put data into an index, you implement the method `IStubElementType.indexStub()` ([example: `JavaClassElementType.indexStub()`](upsource:///java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaClassElementType.java)). This method accepts an `IndexSink` as a parameter, and puts in the index ID and the key for each index in which the element should be stored. +To put data into an index, you implement the method `IStubElementType.indexStub()` ([example: `JavaClassElementType.indexStub()`](upsource:///java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaClassElementType.java)). +This method accepts an `IndexSink` as a parameter and puts in the index ID and the key for each index in which the element should be stored. To access the data from an index, the following two methods are used: @@ -55,5 +76,4 @@ To access the data from an index, the following two methods are used: ## Related Forum Discussions -* [Lifecycle of stub creation](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206121959-Lifecycle-of-stub-creation/comments/206143885) - +* [Lifecycle of stub creation](https://intellij-support.jetbrains.com/hc/en-us/community/posts/206121959-Lifecycle-of-stub-creation/comments/206143885) diff --git a/basics/intellij_coding_guidelines.md b/basics/intellij_coding_guidelines.md index abb096958..a7fb8fedd 100644 --- a/basics/intellij_coding_guidelines.md +++ b/basics/intellij_coding_guidelines.md @@ -7,7 +7,8 @@ If you are writing code that you would like to contribute to the IntelliJ Platfo ## Following the Latest Source Code -If you submit patches, we strongly recommend building your patches against the latest version of the code from the Git repository. The easiest way to do so is to clone the JetBrains Git repository, track your work in Git, and create patches using the "git format-patch" command. +If you submit patches, we strongly recommend building your patches against the latest version of the code from the Git repository. +The easiest way to do so is to clone the JetBrains Git repository, track your work in Git, and create patches using the "git format-patch" command. ## General Architectural Principles @@ -15,7 +16,9 @@ Please do your best to follow common Java architectural principles. "Effective J ## Tests -Functional tests cover most of the existing functionality of IntelliJ IDEA. If tests cover the area you're modifying, you must run the tests and make sure that your changes do not introduce any new test failures. It's also strongly recommended that you provide new functional tests that cover the bugs you fix or the new features that you add. +Functional tests cover most of the existing functionality of IntelliJ IDEA. +If tests cover the area you're modifying, you must run the tests and make sure that your changes do not introduce any new test failures. +It's also strongly recommended that you provide new functional tests that cover the bugs you fix or the new features that you add. ## Code Formatting @@ -29,19 +32,25 @@ The easiest way to follow our code formatting guidelines is to reformat your cod ## Inspections -The IntelliJ IDEA Community Edition project includes a shared inspection profile. We strongly recommend making sure that the code you submit does not contain any warnings highlighted by the inspections configured in that inspection profile. +The IntelliJ IDEA Community Edition project includes a shared inspection profile. +We strongly recommend making sure that the code you submit does not contain any warnings highlighted by the inspections configured in that inspection profile. ## JavaDoc Comments -If your code adds new OpenAPI interfaces, classes, methods, or extension points, you must provide JavaDoc comments describing the parameters and intended usage of the APIs. Providing JavaDoc or other comments for other parts of the code is a good idea but isn't required. +If your code adds new OpenAPI interfaces, classes, methods, or extension points, you must provide JavaDoc comments describing the parameters and intended usage of the APIs. +Providing JavaDoc or other comments for other parts of the code is a good idea but isn't required. ## Commits To avoid unnecessary work when reviewing your changes, please follow these guidelines: -- Look through all of your changes in your patch or pull request before you submit it to us. Make sure that everything you've changed is there for a reason. -- Please don't include unfinished work to the patch. Make sure that it doesn't contain any TODO comments. If you added some code and ended up not needing it, please make sure that you delete it before you submit your patch. -- Please don't include any changes that affect formatting, fixing "yellow code" (warnings), or code style along with actual changes that fix a bug or implement a feature. No one likes to leave poor code, but remember that having these changes mixed complicates the process of review. +- Look through all of your changes in your patch or pull request before you submit it to us. + Make sure that everything you've changed is there for a reason. +- Please don't include unfinished work to the patch. + Make sure that it doesn't contain any TODO comments. + If you added some code and ended up not needing it, please make sure that you delete it before you submit your patch. +- Please don't include any changes that affect formatting, fixing "yellow code" (warnings), or code style along with actual changes that fix a bug or implement a feature. + No one likes to leave poor code, but remember that having these changes mixed complicates the process of review. - Please don't fix multiple problems within a single patch or pull request. - Please don't commit your changes to configuration files (runConfigurations/IDEA.xml, codeStyleSettings.xml, misc.xml, etc.) unless it is essential for the fix itself. - Please avoid moving or renaming classes unless it is necessary for the fix. diff --git a/basics/persisting_sensitive_data.md b/basics/persisting_sensitive_data.md index a5434b4f2..b4530e31d 100644 --- a/basics/persisting_sensitive_data.md +++ b/basics/persisting_sensitive_data.md @@ -3,7 +3,7 @@ title: Persisting Sensitive Data --- -The Credentials Store API allows you to securely store sensitive user data, like passwords, server URLs, etc. +The Credentials Store API allows you to store sensitive user data securely, like passwords, server URLs, etc. ## How to Use Use [`PasswordSafe`](upsource:///platform/platform-api/src/com/intellij/ide/passwordSafe/PasswordSafe.kt) to work with credentials. @@ -13,18 +13,18 @@ Use [`PasswordSafe`](upsource:///platform/platform-api/src/com/intellij/ide/pass ```java String key = null; // e.g. serverURL, accountID CredentialAttributes credentialAttributes = createCredentialAttributes(key); - + Credentials credentials = PasswordSafe.getInstance().get(credentialAttributes); if (credentials != null) { String password = credentials.getPasswordAsString(); } // or get password only - String password = PasswordSafe.getInstance().getPassword(credentialAttributes); - + String password = PasswordSafe.getInstance().getPassword(credentialAttributes); + private CredentialAttributes createCredentialAttributes(String key) { - return new CredentialAttributes(CredentialAttributesKt.generateServiceName("MySystem", key)); - } + return new CredentialAttributes(CredentialAttributesKt.generateServiceName("MySystem", key)); + } ``` ### Store Credentials @@ -35,10 +35,10 @@ Use [`PasswordSafe`](upsource:///platform/platform-api/src/com/intellij/ide/pass PasswordSafe.getInstance().set(credentialAttributes, credentials); ``` -To remove stored credentials, pass `null` for `credentials` parameter. +To remove stored credentials, pass `null` for the `credentials` parameter. ## Storage -Default storage format depends on OS. +The default storage format depends on the OS. | OS | Storage | |---------|---------| @@ -46,4 +46,4 @@ Default storage format depends on OS. | 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) | -Users can override the default behavior in Preferences \| Appearance & Behavior \| System Settings \| Passwords. \ No newline at end of file +Users can override the default behavior in Preferences \| Appearance & Behavior \| System Settings \| Passwords. diff --git a/basics/persisting_state_of_components.md b/basics/persisting_state_of_components.md index c5da84943..9aca0548d 100644 --- a/basics/persisting_state_of_components.md +++ b/basics/persisting_state_of_components.md @@ -3,13 +3,16 @@ title: Persisting State of Components --- -The *IntelliJ Platform* provides an API that allows components or services to persist their state between restarts of the IDE. You can use either a simple API to persist a few values or persist the state of more complicated components using the [`PersistentStateComponent`](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) interface. +The *IntelliJ Platform* provides an API that allows components or services to persist their state between restarts of the IDE. +You can use either a simple API to persist a few values or persist the state of more complicated components using the [`PersistentStateComponent`](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) interface. > **WARNING** If you need to persist sensitive data like passwords, please see [Persisting Sensitive Data](persisting_sensitive_data.md). ## Using PropertiesComponent for Simple Non-Roamable Persistence -If the plugin needs to persist just a few simple values, the easiest way to do so is to use the [`com.intellij.ide.util.PropertiesComponent`](upsource:///platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java) service. It can be used for saving both application-level values and project-level values (stored in the workspace file). Roaming is disabled for `PropertiesComponent`, so use it only for temporary, non-roamable properties. +If the plugin needs to persist just a few simple values, the easiest way to do so is to use the [`com.intellij.ide.util.PropertiesComponent`](upsource:///platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java) service. +It can save both application-level values and project-level values in the workspace file. +Roaming is disabled for `PropertiesComponent`, so use it only for temporary, non-roamable properties. Use the `PropertiesComponent.getInstance()` method for storing application-level values, and the `PropertiesComponent.getInstance(Project)` method for storing project-level values. @@ -24,18 +27,20 @@ To use it: - define the state class - specify the storage location using `@com.intellij.openapi.components.State` -Note that instances of extensions cannot persist their state by implementing `PersistentStateComponent`. If your extension needs to have a persistent state, you need to define a separate service responsible for managing that state. +Note that instances of extensions cannot persist their state by implementing `PersistentStateComponent`. +If your extension needs to have a persistent state, you need to define a separate service responsible for managing that state. ### Implementing the PersistentStateComponent Interface -The implementation of `PersistentStateComponent` needs to be parameterized with the type of the state class. The state class can either be a separate JavaBean class, or the class implementing `PersistentStateComponent` itself. +The implementation of `PersistentStateComponent` needs to be parameterized with the type of state class. +The state class can either be a separate JavaBean class, or the class implementing `PersistentStateComponent`. -In the former case, the instance of the state class is typically stored as a field in the `PersistentStateComponent` class: +In the former case, the state class instance is typically stored as a field in the `PersistentStateComponent` class: ```java @State(...) class MyService implements PersistentStateComponent { - + static class State { public String value; } @@ -71,13 +76,15 @@ class MyService implements PersistentStateComponent { ### 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`. -Note that the state class must have a default constructor. It should return the default state of the component (one used if there is nothing persisted in the XML files yet). +Note that the state class must have a default constructor. +It should return the component's default state: the one used if there is nothing persisted in the XML files yet. -State class should have an `equals()` method, but if it is not implemented, state objects are compared by fields. When using Kotlin, use [Data Classes](https://kotlinlang.org/docs/reference/data-classes.html). +State class should have an `equals()` method, but state objects are compared by fields if it is not implemented. +When using Kotlin, use [Data Classes](https://kotlinlang.org/docs/reference/data-classes.html). The following types of values can be persisted: @@ -119,12 +126,13 @@ class State { ### Defining the Storage Location -To specify where exactly the persisted values are stored, add `@State` annotation to the `PersistentStateComponent` class. +To specify where precisely the persisted values are stored, add `@State` annotation to the `PersistentStateComponent` class. It has the following fields: * `name` (required) — specifies the name of the state (name of the root tag in XML). -* `storages` — one or more of `@com.intellij.openapi.components.Storage` annotations to specify the storage locations. Optional for project-level values — standard project file is used in this case. -* `reloadable` (optional) — if set to false, complete project (or application) reload is required when the XML file is changed externally and the state has changed. +* `storages` — one or more of `@com.intellij.openapi.components.Storage` annotations to specify the storage locations. + Optional for project-level values — standard project file is used in this case. +* `reloadable` (optional) — if set to false, complete project (or application) reload is required when the XML file is changed externally, and the state has changed. The simplest ways of specifying the `@Storage` annotation are as follows (since 2016.x; for previous versions, please see [old version](https://github.com/JetBrains/intellij-sdk-docs/blob/5dcb02991cf828a7d4680d125ce56b4c10234146/basics/persisting_state_of_components.md) of this document): @@ -132,40 +140,48 @@ The simplest ways of specifying the `@Storage` annotation are as follows (since * `@Storage(StoragePathMacros.WORKSPACE_FILE)` for values stored in the workspace file. -By specifying a different value for the `value` parameter (`file` before 2016.x), the state is persisted in a different file. +The state is persisted in a separate file by specifying a different setting for the `value` parameter, which was the `file` parameter before 2016.x. -> **NOTE** For application-level components it is strongly recommended to use a custom file, using of `other.xml` is deprecated. +> **NOTE** For application-level components, it is strongly recommended to use a custom file, using of `other.xml` is deprecated. The `roamingType` parameter of the `@Storage` annotation specifies the roaming type when the Settings Repository plugin is used. ## Customizing the XML Format of Persisted Values -> **NOTE** Please consider using annotation parameters only to achieve backward compatibility. Otherwise, please feel free to file issues about serialization cosmetics. +> **NOTE** Please consider using annotation parameters only to achieve backward compatibility. +> Otherwise, please feel free to file issues about serialization cosmetics. -If you want to use the default bean serialization but need to customize the storage format in XML (for example, for compatibility with previous versions of your plugin or externally defined XML formats), you can use the `@Tag`, `@Attribute`, `@Property`, `@MapAnnotation`, `@AbstractCollection` annotations. +If you want to use the default bean serialization but need to customize the storage format in XML (for example, for compatibility with previous versions of your plugin or externally defined XML formats), you can use the `@Tag`, `@Attribute`, `@Property`, `@MapAnnotation`, `@AbstractCollection` annotations. Please see `com.intellij.util.xmlb.annotations`'s [`package.html`](upsource:///platform/util/src/com/intellij/util/xmlb/annotations/package.html) for more information. -If the state you need to serialize doesn't map cleanly to a JavaBean, you can use `org.jdom.Element` as the state class. In that case, you can use the `getState()` method to build an XML element with an arbitrary structure, which then is saved directly in the state XML file. In the `loadState()` method, you can deserialize the JDOM element tree using any custom logic. Please note this is not recommended and should be avoided whenever possible. +If the state you need to serialize doesn't map cleanly to a JavaBean, you can use `org.jdom.Element` as the state class. +In that case, you can use the `getState()` method to build an XML element with an arbitrary structure, which then is saved directly in the state XML file. +In the `loadState()` method, you can deserialize the JDOM element tree using any custom logic. +Please note this is not recommended and should be avoided whenever possible. ## Migrating Persisted Values -If the underlying persistence model or storage format has changed, a [`ConverterProvider`](upsource:///platform/lang-impl/src/com/intellij/conversion/ConverterProvider.java) can provide -[`ProjectConverter`](upsource:///platform/lang-impl/src/com/intellij/conversion/ProjectConverter.java) whose `getAdditionalAffectedFiles()` method returns affected files to migrate and performs programmatic migration of stored values. +If the underlying persistence model or storage format has changed, a [`ConverterProvider`](upsource:///platform/lang-impl/src/com/intellij/conversion/ConverterProvider.java) can provide [`ProjectConverter`](upsource:///platform/lang-impl/src/com/intellij/conversion/ProjectConverter.java) whose `getAdditionalAffectedFiles()` method returns affected files to migrate and performs programmatic migration of stored values. ## Persistent Component Lifecycle -The `loadState()` method is called after the component has been created (only if there is some non-default state persisted for the component), and after the XML file with the persisted state is changed externally (for example, if the project file was updated from the version control system). In the latter case, the component is responsible for updating the UI and other related components according to the changed state. +The `loadState()` method is called after the component has been created (only if there is some non-default state persisted for the component), and after the XML file with the persisted state is changed externally (for example, if the project file was updated from the version control system). +In the latter case, the component is responsible for updating the UI and other related components according to the changed state. -The `getState()` method is called every time the settings are saved (for example, on frame deactivation or when closing the IDE). If the state returned from `getState()` is equal to the default state (obtained by creating the state class with a default constructor), nothing is persisted in the XML. Otherwise, the returned state is serialized in XML and stored. +The `getState()` method is called every time the settings are saved (for example, on frame deactivation or when closing the IDE). +If the state returned from `getState()` is equal to the default state (obtained by creating the state class with a default constructor), nothing is persisted in the XML. +Otherwise, the returned state is serialized in XML and stored. ## Legacy API (JDOMExternalizable) -Older components use the [`JDOMExternalizable`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) interface for persisting state. It uses the `readExternal()` method for reading the state from a JDOM element, and `writeExternal()` to write the state to it. +Older components use the [`JDOMExternalizable`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) interface for persisting state. +It uses the `readExternal()` method for reading the state from a JDOM element, and `writeExternal()` to write the state. -Implementations can store the state in attributes and sub-elements manually, or use the [`DefaultJDOMExternalizer`](upsource:///platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java) class to store the values of all public fields automatically. +Implementations can manually store the state in attributes and sub-elements or use the [`DefaultJDOMExternalizer`](upsource:///platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java) class to store the values of all public fields automatically. Components save their state in the following files: -* Project-level: project (`.ipr`) file. However, if the workspace option in the `plugin.xml` file is set to `true`, then workspace (`.iws`) file is used instead. +* Project-level: project (`.ipr`) file. + However, if the workspace option in the `plugin.xml` file is set to `true`, then the workspace (`.iws`) file is used instead. * Module-level: module (`.iml`) file. diff --git a/basics/platform_contributions.md b/basics/platform_contributions.md index bcdf3675c..75566c612 100644 --- a/basics/platform_contributions.md +++ b/basics/platform_contributions.md @@ -7,42 +7,60 @@ Please make sure to read the [Code of Conduct](/CODE_OF_CONDUCT.md). ## Participate in the Community -### Participate in Newsgroups and Forums -There are several community [forums and newsgroups](https://intellij-support.jetbrains.com/hc/en-us/community/topics) you can join to discuss the IntelliJ Platform. The forums are an excellent source for users and contributors interested in having technical discussions, answering questions, or resolving potential issues for newcomers. +### 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. ### Link to jetbrains.org -The success of any open-source project depends on the number of people who use the product and contribute back to the project. By linking to jetbrains.org, you can increase the chances of a new user or contributor finding out about the project and joining the community. +The success of any open-source project depends on the number of people who use the product and contribute back to the project. +By linking to jetbrains.org, you can increase the chances of a new user or contributor finding out about the project and joining the community. -If you're as excited about IntelliJ IDEA Community Edition as we are, you can show it by linking to us. Project logos and other assets are [also available](https://www.jetbrains.com/company/press/). +If you're as excited about IntelliJ IDEA Community Edition as we are, you can show it by linking to us. +Project logos and other assets are [also available](https://www.jetbrains.com/company/press/). -### Promote IntelliJ Platform and IntelliJ IDEA Community Edition -Help promote the platform and IDE by using your blog, Twitter, Facebook, or submitting an article to your favorite local magazine. If you are a member of a different open-source community, why not mention IntelliJ IDEA on their discussion forums or at conferences? If you love IntelliJ IDEA, don't hold back - speak up! The more developers use IntelliJ IDEA, the more bugs will be caught, the more plugins will be written, the more visible the project, and the more benefits the community will get! +### 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 Others Learn ### Write Documents -We're always looking for new articles about IntelliJ IDEA features as well as documentation for the IntelliJ Platform. You can write tutorials, how-tos, sample applications, or share your experience with the IntelliJ Platform. You can publish your documentation on a website or blog, or submit a [pull request](/CONTRIBUTING.md) to the SDK Docs. +We're always looking for new articles about IntelliJ IDEA features as well as documentation for the IntelliJ Platform. +You can write tutorials, how-tos, sample applications, or share your experience with the IntelliJ Platform. +You can publish your documentation on a website or blog, or submit a [pull request](/CONTRIBUTING.md) to the SDK Docs. ### Produce Screencasts -Screencasts have recently become very popular as a way to show other developers how to use the tool effectively. You can record a screencast about a particular feature or use case you discovered and would like to share it with the community. +Screencasts have recently become very popular as a way to show other developers how to use the tool effectively. +You can record a screencast about a particular feature or use case you discovered and would like to share it with the community. ## Contribute Code ### File a Bug Report -Bug reports take little time to file and are very helpful to developers. This is one of the easiest contributions you can make. When you discover a problem with the IDE or the platform, please report it. Make sure you provide information about your environment (OS, JDK version), steps to reproduce the issue, as well as a written description of the problem. You can file a bug in our [YouTrack issue tracker](https://youtrack.jetbrains.com/issues/IDEA). +Bug reports take little time to file and are very helpful to developers. +This is one of the easiest contributions you can make. +When you discover a problem with the IDE or the platform, please report it. +Make sure you provide information about your environment (OS, JDK version), steps to reproduce the issue, as well as a written description of the problem. +You can file a bug in our [YouTrack issue tracker](https://youtrack.jetbrains.com/issues/IDEA). Before submitting an issue, please search for already submitted ones describing the same problem - and if you find one, feel free to vote for it. ### Help Triage Existing Bug Reports -Over the years, users have submitted thousands of issues to the IntelliJ issue tracker. Many of the unresolved issues are no longer applicable to the latest version of IntelliJ IDEA, are duplicates, or require additional information to be resolved. Leaving comments notifying about the status of such issues helps the team keep the issue tracker clean and useful for everyone. +Over the years, users have submitted thousands of issues to the IntelliJ issue tracker. +Many of the unresolved issues are no longer applicable to the latest version of IntelliJ IDEA, are duplicates, or require additional information to be resolved. +Leaving comments notifying about the status of such issues helps the team keep the issue tracker clean and useful for everyone. ### Write a Plugin -One of the best ways to contribute a larger piece of code, adding extra functionality to IntelliJ IDEA or any of the other IntelliJ Platform-based IDEs, is by writing a plugin. You can submit a plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com/), making it available for all users. When writing a plugin, you have control over the code and don't need to sign the contribution agreement. +One of the best ways to contribute a larger piece of code, adding extra functionality to IntelliJ IDEA or any of the other IntelliJ Platform-based IDEs, is by writing a plugin. +You can submit a plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com/), making it available for all users. +When writing a plugin, you have control over the code and don't need to sign the contribution agreement. ### Submit a Patch -If you would like to improve the code in the IntelliJ Platform or the core functionality of IntelliJ IDEA, you can submit a patch in the [YouTrack bug database](https://youtrack.jetbrains.com/issues/IDEA). You can either file a new issue with the patch attached or attach a patch to an issue submitted by another user. When writing a patch, please make sure to follow the [IntelliJ Platform Coding Guidelines](intellij_coding_guidelines.md). +If you would like to improve the code in the IntelliJ Platform or the core functionality of IntelliJ IDEA, you can submit a patch in the [YouTrack bug database](https://youtrack.jetbrains.com/issues/IDEA). +You can either file a new issue with the patch attached or attach a patch to an issue submitted by another user. +When writing a patch, please make sure to follow the [IntelliJ Platform Coding Guidelines](intellij_coding_guidelines.md). Alternatively, you can fork the [IntelliJ IDEA Community Edition repository on GitHub](https://github.com/JetBrains/intellij-community), make the changes in your fork and send us a pull request. -A developer will review your patch and, if it meets the [quality criteria](intellij_coding_guidelines.md) and fits well with the rest of the code, you'll be notified about the acceptance of the patch. You will also need to sign the [JetBrains Contributor License Agreement (CLA)](https://www.jetbrains.com/agreements/cla/) to complete your contribution. +A developer will review your patch and, if it meets the [quality criteria](intellij_coding_guidelines.md) and fits well with the rest of the code, you'll be notified about the acceptance of the patch. +You will also need to sign the [JetBrains Contributor License Agreement (CLA)](https://www.jetbrains.com/agreements/cla/) to complete your contribution. ### Become a Committer Developers with a long history of submitting high-quality patches can gain direct commit rights. diff --git a/basics/plugin_structure/dynamic_plugins.md b/basics/plugin_structure/dynamic_plugins.md index 00d9a502c..c28daa8e5 100644 --- a/basics/plugin_structure/dynamic_plugins.md +++ b/basics/plugin_structure/dynamic_plugins.md @@ -3,22 +3,22 @@ title: Dynamic Plugins --- -Starting with 2020.1 release, the ability to install, update and uninstall plugins without restarting the IDE is available in the IntelliJ Platform. +Starting with the 2020.1 release, installing, updating, and uninstalling plugins without restarting the IDE is available in the IntelliJ Platform. During plugin development, [Auto-Reload](/basics/ide_development_instance.md#enabling-auto-reload) also allows code changes to take effect immediately in the sandbox IDE instance. > **NOTE** If a plugin _requires_ restart (e.g., due to using native libraries) specify `require-restart="true"` for `` root tag in `plugin.xml`. ## Restrictions -For a plugin to support this, all restrictions listed below must be met. To verify a plugin locally, run _Plugin DevKit | Plugin descriptor | Plugin.xml dynamic plugin verification_ -inspection on all plugin descriptor files (required `plugin.xml` as well as any additional files). +For a plugin to support this, all restrictions listed below must be met. +To verify a plugin locally, run **Analyize \| Run Inspection by Name... \| Plugin.xml dynamic plugin verification** inspection on all plugin descriptor files. -For plugins hosted on the [JetBrains Plugins Repository](https://plugins.jetbrains.com) the built-in [Plugin Verifier](https://blog.jetbrains.com/platform/2018/07/plugins-repository-now-integrates-with-the-plugin-verification-tool/) -will run these checks automatically. See [Plugin Verifier](/reference_guide/api_changes_list.md#plugin-verifier) for more information on how to run it locally. +For plugins hosted on the [JetBrains Plugins Repository](https://plugins.jetbrains.com) the built-in [Plugin Verifier](https://blog.jetbrains.com/platform/2018/07/plugins-repository-now-integrates-with-the-plugin-verification-tool/) will run these checks automatically. +See [Plugin Verifier](/reference_guide/api_changes_list.md#plugin-verifier) for more information on how to run it locally. ### No Use of Components -No Components must be used; existing ones [must be migrated](plugin_components.md) to services, extensions or listeners. +No Components must be used; existing ones [must be migrated](plugin_components.md) to services, extensions, or listeners. ### Action Group Requires ID @@ -26,13 +26,13 @@ All ``s must declare a unique `id`. ### Use Only Dynamic Extensions -All extensions, whether defined in the platform itself or coming from other plugins, must be marked as dynamic (see next paragraph). +Whether defined in the platform itself or coming from other plugins, all extensions must be marked as dynamic (see next paragraph). Some deprecated extension points (e.g., `com.intellij.configurationProducer`) are intentionally non-dynamic, and their usage should be migrated to the corresponding replacement. ### Mark Extension Points as Dynamic -All extension points provided by the plugin must adhere to specific usage rules and then [be declared](plugin_extension_points.md#dynamic-extension-points) ready for dynamic use explicitly. +The plugin's extension points must adhere to specific usage rules and then [be declared](plugin_extension_points.md#dynamic-extension-points) ready for dynamic use explicitly. ### Configurables Depending on Extension Points @@ -40,7 +40,7 @@ Any `Configurable` which depends on dynamic extension points must implement `Con ### No Use of Service Overrides -Application, project and module services declared with `overrides="true"` are not allowed. +Application, project, and module services declared with `overrides="true"` are not allowed. ## Code @@ -52,7 +52,7 @@ Loading/Unloading a plugin clears all cached values created using `CachedValuesM ### Do not Store PSI -Do not store references to PSI elements in objects which can survive plugin loading or unloading, use `SmartPsiElementPointer` instead. +Do not store references to PSI elements in objects which can survive plugin loading or unloading; use `SmartPsiElementPointer` instead. ### Do not Use FileType/Language as Map Key @@ -62,7 +62,7 @@ Replace with `String` from `Language.getID()`/`FileType.getName()`. Register [`com.intellij.ide.plugins.DynamicPluginListener`](upsource:///platform/platform-impl/src/com/intellij/ide/plugins/DynamicPlugins.kt) [application listener](plugin_listeners.md) to receive updates on plugin load/unload events. -This can be used to e.g. cancel long-running activities or disallow unload due to ongoing processes. +This can be used to e.g., cancel long-running activities or disallow unload due to ongoing processes. ## Troubleshooting @@ -80,4 +80,5 @@ To find leaks preventing clean unload, perform the following steps: - Verify that IDE runs with VM parameter `-XX:+UnlockDiagnosticVMOptions` - Open the `.hprof` snapshot generated on plugin unload, look for the plugin ID string - Find the `PluginClassLoader` referencing the plugin ID string -- Look at references to the `PluginClassLoader` instance. Every one of them is a memory leak (or part of a memory leak) that needs to be resolved. +- Look at references to the `PluginClassLoader` instance. + Every one of them is a memory leak (or part of a memory leak) that needs to be resolved. diff --git a/basics/plugin_structure/plugin_actions.md b/basics/plugin_structure/plugin_actions.md index 6146dd440..569fefb57 100644 --- a/basics/plugin_structure/plugin_actions.md +++ b/basics/plugin_structure/plugin_actions.md @@ -3,15 +3,16 @@ title: Plugin Actions --- -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. -Actions are the most common way for a user to invoke the functionality of your plugin. An action can be invoked from -a menu or a toolbar, using a keyboard shortcut, or from the **Help \| Find Action...** lookup. +Actions are the most common way for a user to invoke the functionality of your plugin. +An action can be invoked from a menu or a toolbar, using a keyboard shortcut or the **Help \| Find Action...** lookup. -Actions are organized into groups, which, in turn, can contain other groups. A group of actions can form a toolbar or a menu. +Actions are organized into groups, which, in turn, can contain other groups. +A group of actions can form a toolbar or a menu. Subgroups of the group can form submenus of a menu. -The user can customize all registered actions via [Menus and Toolbars](https://www.jetbrains.com/help/idea/customize-actions-menus-and-toolbars.html) settings. +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. diff --git a/basics/plugin_structure/plugin_class_loaders.md b/basics/plugin_structure/plugin_class_loaders.md index 3d6ceee45..412790766 100644 --- a/basics/plugin_structure/plugin_class_loaders.md +++ b/basics/plugin_structure/plugin_class_loaders.md @@ -3,12 +3,16 @@ title: Plugin Class Loaders --- -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 `` 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 `` element to specify that a [plugin depends](plugin_class_loaders.md) on one or more other plugins. +In this case, the class loaders of those plugins will be used for classes not found in the current plugin. +This allows a plugin to reference classes from other plugins. ### Using ServiceLoader -Some libraries use [`ServiceLoader`](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/ServiceLoader.html) to detect and load implementations. +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: ```java @@ -19,4 +23,4 @@ For this to work in a plugin, the context class loader must be set to the plugin } finally { Thread.currentThread().setContextClassLoader(current); } -``` \ No newline at end of file +``` diff --git a/basics/plugin_structure/plugin_components.md b/basics/plugin_structure/plugin_components.md index df8787c0a..cfab234e3 100644 --- a/basics/plugin_structure/plugin_components.md +++ b/basics/plugin_structure/plugin_components.md @@ -3,26 +3,24 @@ title: Plugin Components --- -> **WARNING** When writing new plugins, creating components should be avoided. Any existing components should be migrated to services, extensions, or listeners (see below). +> **WARNING** When writing new plugins, creating components should be avoided. +> Any existing components should be migrated to services, extensions, or listeners (see below). -Plugin components are a legacy feature supported for compatibility with plugins created for older versions of the -IntelliJ Platform. Plugins using components do not support [dynamic loading](dynamic_plugins.md) (the ability to install, update, and -uninstall plugins without restarting the IDE). +Plugin components are a legacy feature supported for compatibility with plugins created for older versions of the IntelliJ Platform. +Plugins using components do not support [dynamic loading](dynamic_plugins.md) (the ability to install, update, and uninstall plugins without restarting the IDE). + +Plugin components are defined using ``, ``, and `` tags in a `plugin.xml` file. -Plugin components are defined using ``, ``, and `` -tags in a `plugin.xml` file. - ## Migration To migrate existing code from components to more modern APIs, please use the following guidelines: - * To manage some state or logic that is only needed when the user performs a specific operation, - use a [Service](plugin_services.md). - * To store the state of your plugin at the application or project level, use a [Service](plugin_services.md), - and implement the `PersistentStateComponent` interface. See [Persisting State of Components](/basics/persisting_state_of_components.md) for details. - * To subscribe to events, use a [listener](plugin_listeners.md) or create an [extension](plugin_extensions.md) for a dedicated extension point (for example, `com.intellij.editorFactoryListener`) if one exists for the event to subscribe to. - * Executing code on application startup should be avoided whenever possible because it slows down startup. - Plugin code should only be executed when projects are opened or when the user invokes an action of a plugin. If this cannot be avoided, add a [listener](plugin_listeners.md) subscribing to the [AppLifecycleListener](upsource:///platform/platform-impl/src/com/intellij/ide/AppLifecycleListener.java) topic. - * To execute code when a project is being opened, provide [StartupActivity](upsource:///platform/core-api/src/com/intellij/openapi/startup/StartupActivity.java) implementation and register an [extension](plugin_extensions.md) for the `com.intellij.postStartupActivity` or `com.intellij.backgroundPostStartupActivity` extension point (the latter is supported starting with version 2019.3 of the platform). - * To execute code on project closing or application shutdown, implement the `Disposable` interface in a [Service](plugin_services.md) - and place the code in the `dispose()` method. Alternatively, use `Disposer.register()` passing a `Project` or `Application` service instance - as the `parent` argument (see [Choosing a Disposable Parent](/basics/disposers.md#choosing-a-disposable-parent)). +* To manage some state or logic that is only needed when the user performs a specific operation, use a [Service](plugin_services.md). +* To store the state of your plugin at the application or project level, use a [Service](plugin_services.md), and implement the `PersistentStateComponent` interface. + See [Persisting State of Components](/basics/persisting_state_of_components.md) for details. +* To subscribe to events, use a [listener](plugin_listeners.md) or create an [extension](plugin_extensions.md) for a dedicated extension point (for example, `com.intellij.editorFactoryListener`) if one exists for the event to subscribe to. +* Executing code on application startup should be avoided whenever possible because it slows down startup. + Plugin code should only be executed when projects are opened or when the user invokes an action of a plugin. + If this cannot be avoided, add a [listener](plugin_listeners.md) subscribing to the [AppLifecycleListener](upsource:///platform/platform-impl/src/com/intellij/ide/AppLifecycleListener.java) topic. +* To execute code when a project is being opened, provide [StartupActivity](upsource:///platform/core-api/src/com/intellij/openapi/startup/StartupActivity.java) implementation and register an [extension](plugin_extensions.md) for the `com.intellij.postStartupActivity` or `com.intellij.backgroundPostStartupActivity` extension point (the latter is supported starting with version 2019.3 of the platform). +* To execute code on project closing or application shutdown, implement the `Disposable` interface in a [Service](plugin_services.md) and place the code in the `dispose()` method. + Alternatively, use `Disposer.register()` passing a `Project` or `Application` service instance as the `parent` argument (see [Choosing a Disposable Parent](/basics/disposers.md#choosing-a-disposable-parent)). diff --git a/basics/plugin_structure/plugin_configuration_file.md b/basics/plugin_structure/plugin_configuration_file.md index a8a64cdf6..0bd164780 100644 --- a/basics/plugin_structure/plugin_configuration_file.md +++ b/basics/plugin_structure/plugin_configuration_file.md @@ -3,12 +3,13 @@ title: Plugin Configuration File - plugin.xml --- -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 `` is available in the [Actions](/basics/action_system.md#registering-actions) section in Part II. Limited HTML elements are allowed within `` and `` elements. -However, content containing HTML elements must be surrounded by `` tags. -Allowed HTML elements include text formatting, paragraphs, and lists. +However, content containing HTML elements must be surrounded by `` tags. +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). @@ -16,25 +17,25 @@ When using Gradle, a number of metadata elements will be provided at build time - Vss Integration - com.jetbrains.vssintegration - Integrates Volume Snapshot Service W10 @@ -57,7 +58,7 @@ When using Gradle, a number of metadata elements will be provided at build time com.intellij.modules.platform com.third.party.plugin @@ -75,7 +76,7 @@ When using Gradle, a number of metadata elements will be provided at build time `action.[ActionID].text|description` --> messages.MyPluginBundle - @@ -88,7 +89,7 @@ When using Gradle, a number of metadata elements will be provided at build time - @@ -126,7 +127,7 @@ When using Gradle, a number of metadata elements will be provided at build time @@ -135,7 +136,7 @@ When using Gradle, a number of metadata elements will be provided at build time diff --git a/basics/plugin_structure/plugin_content.md b/basics/plugin_structure/plugin_content.md index fae690600..a77f87089 100644 --- a/basics/plugin_structure/plugin_content.md +++ b/basics/plugin_structure/plugin_content.md @@ -5,11 +5,11 @@ title: Plugin Content The plugin `jar` file must contain: - the configuration file (`META-INF/plugin.xml`) ([Plugin Configuration File](plugin_configuration_file.md)) -- the classes that implement the plugin functionality -- recommended: plugin logo file(s) (`META-INF/pluginIcon*.svg`) ([Plugin Logo](plugin_icon_file.md)) +- the classes that implement the plugin functionality +- 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. ```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. All jars from the `/lib` folder are automatically added to the classpath (see also [Plugin Class Loaders](plugin_class_loaders.md)). - + ```text .IntelliJIDEAx0/ └── plugins diff --git a/basics/plugin_structure/plugin_dependencies.md b/basics/plugin_structure/plugin_dependencies.md index ebe8503e0..9eb0d7968 100644 --- a/basics/plugin_structure/plugin_dependencies.md +++ b/basics/plugin_structure/plugin_dependencies.md @@ -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. 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: ## 1. Locating Plugin ID and Preparing Sandbox For plugins published on [JetBrains Plugins Repository](https://plugins.jetbrains.com) -- open plugin's detail page +- open plugin's detail page - select _Versions_ tab - 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 > **NOTE** Please see the `plugins` attribute [gradle-intellij-plugin: Configuration](https://github.com/JetBrains/gradle-intellij-plugin#configuration) for acceptable values. -If the project is using [Gradle](/tutorials/build_system.md) with a Groovy build script to build the plugin, add the dependency to the `plugins` parameter of the `intellij` block in your `build.gradle`, for example: +If the project uses [Gradle](/tutorials/build_system.md) with a Groovy build script to build the plugin, add the dependency to the `plugins` parameter of the `intellij` block in your `build.gradle`, for example: ```groovy intellij { @@ -41,31 +41,30 @@ When using Kotlin build script, use `setPlugins()` within the `intellij` block, intellij { 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 > **TIP** Existing DevKit-based projects can be converted to use [Gradle setup](/tutorials/build_system/prerequisites.md#adding-gradle-support-to-an-existing-devkit-based-intellij-platform-plugin) where managing dependencies is fully automated. -If the project is using [DevKit](/basics/getting_started/using_dev_kit.md), add the JARs of the plugin on which the project depends to the **classpath** of the *IntelliJ Platform SDK*. +If the project uses [DevKit](/basics/getting_started/using_dev_kit.md), add the JARs of the plugin on which the project depends to the **classpath** of the *IntelliJ Platform SDK*. > **WARNING** Do not add the plugin JARs as a library: this will fail at runtime because the IntelliJ Platform will load two separate copies of the dependency plugin classes. -To do that, open the Project Structure dialog, select the SDK used in the project, press the + button in the Classpath tab, and -select the plugin JAR file or files: +To do that, open the Project Structure dialog, select the SDK used in the project, press the + button in the Classpath tab, and select the plugin JAR file or files: * For bundled plugins, the plugin JAR files are located in `plugins/` or `plugins//lib` under the main installation directory. If you're not sure which JAR to add, you can add all of them. * For non-bundled plugins, the plugin JAR files are located in `config/plugins/` or `config/plugins//lib` under the directory specified as "Sandbox Home" in the IntelliJ Platform Plugin SDK settings. ## 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 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 `` element contents while editing the plugin project's `plugin.xml` file. ### 3.1 Configuring plugin.xml -In the `plugin.xml`, add a `` tag with the ID of the dependency plugin as its content. +In the `plugin.xml`, add a `` tag with the dependency plugin's ID as its content. Continuing with the example from [Section 2](#2-project-setup) above, the dependency declaration in `plugin.xml` would be: ```xml @@ -74,11 +73,11 @@ Continuing with the example from [Section 2](#2-project-setup) above, the depend ## Optional Plugin Dependencies -A project can also specify an optional plugin dependency. In this case, the plugin will load even if the plugin it depends on -is not installed or enabled, but part of the functionality of the plugin will not be available. In order to do that, -add `optional="true" config-file="otherconfig.xml"` to the `` tag. +A project can also specify an optional plugin dependency. +In this case, the plugin will load even if the plugin depends on is not installed or enabled, but part of the plugin's functionality will not be available. +In order to do that, add `optional="true" config-file="otherconfig.xml"` to the `` 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: _plugin.xml_ @@ -94,7 +93,8 @@ _plugin.xml_ ``` -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_ diff --git a/basics/plugin_structure/plugin_extension_points.md b/basics/plugin_structure/plugin_extension_points.md index b3dbaca9a..14f6a2388 100644 --- a/basics/plugin_structure/plugin_extension_points.md +++ b/basics/plugin_structure/plugin_extension_points.md @@ -5,44 +5,47 @@ title: Plugin Extension Points > **NOTE** See [Plugin Extensions](plugin_extensions.md) for _using_ extension points in your plugin. -By defining _extension points_ in your plugin, you can allow other plugins to extend the functionality of your plugin. +By defining _extension points_ in your plugin, you can allow other plugins to extend your plugin's functionality. There are two types of extension points: - * _Interface_ extension points allow other plugins to extend your plugins with _code_. When you define an interface - extension point, you specify an interface, and other plugins will provide classes implementing that interface. - You'll then be able to invoke methods on those interfaces. - * _Bean_ extension points allow other plugins to extend your plugins with _data_. You specify the fully qualified - name of an extension class, and other plugins will provide data which will be turned into instances of that class. +* _Interface_ extension points allow other plugins to extend your plugins with _code_. + When you define an interface extension point, you specify an interface, and other plugins will provide classes implementing that interface. + You'll then be able to invoke methods on those interfaces. +* _Bean_ extension points allow other plugins to extend your plugins with _data_. + You specify the fully qualified name of an extension class, and other plugins will provide data that will be turned into instances of that class. ## Declaring Extension Points -You can declare extensions and extension points in the plugin configuration file `plugin.xml`, within the `` and `` sections, respectively. +You can declare extensions and extension points in the plugin configuration file `plugin.xml`, within the `` and `` sections. -To declare extension points in your plugin, add an `` section to your `plugin.xml`. Then insert a child element `` 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 `` section to your `plugin.xml`. +Then insert a child element `` 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_ -```xml +```xml my.plugin - + - - - ``` -The `name` attribute assigns a unique name for this extension point, it will be prefixed with the plugin's `` automatically. +The `name` attribute assigns a unique name for this extension point. +It will be prefixed with the plugin's `` automatically. The `beanClass` attribute sets a bean class that specifies one or several properties annotated with the [`@Attribute`](upsource:///platform/util/src/com/intellij/util/xmlb/annotations/Attribute.java) annotation. The `interface` attribute sets an interface the plugin that contributes to the extension point must implement. -The `area` attribute determines the scope in which the extension will be instantiated. As extensions should be stateless, it is **not** recommended to use non-default. +The `area` attribute determines the scope in which the extension will be instantiated. +As extensions should be stateless, it is **not** recommended to use non-default. Must be one of `IDEA_APPLICATION` for Application (default), `IDEA_PROJECT` for Project, or `IDEA_MODULE` for Module scope. The plugin that contributes to the extension point will read those properties from the `plugin.xml` file. @@ -55,7 +58,7 @@ _myPlugin/src/com/myplugin/MyBeanClass.java_ ```java public class MyBeanClass extends AbstractExtensionPointBean { - + @Attribute("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. 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_ ```xml another.plugin - - + + my.plugin - + - + @@ -101,22 +104,22 @@ To refer to all registered extension instances at runtime, declare an [`Extensio _myPlugin/src/com/myplugin/MyExtensionUsingService.java_ -```java +```java public class MyExtensionUsingService { - - private static final ExtensionPointName EP_NAME = + + private static final ExtensionPointName EP_NAME = ExtensionPointName.create("my.plugin.myExtensionPoint1"); - + public void useExtensions() { for (MyBeanClass extension : EP_NAME.getExtensionList()) { - String key = extension.getKey(); + String key = extension.getKey(); String clazz = extension.getClass(); // ... } } } ``` - + A gutter icon for the `ExtensionPointName` declaration allows navigating to the corresponding `` declaration in `plugin.xml`. ## Dynamic Extension Points @@ -129,10 +132,11 @@ Extension points matching these conditions can then be marked as _dynamic_ by ad ```xml - ``` -> **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". diff --git a/basics/plugin_structure/plugin_extensions.md b/basics/plugin_structure/plugin_extensions.md index 0c515fb7e..7e02cb29a 100644 --- a/basics/plugin_structure/plugin_extensions.md +++ b/basics/plugin_structure/plugin_extensions.md @@ -5,29 +5,29 @@ redirect_from: --- -_Extensions_ are the most common way for a plugin to extend the functionality of the IntelliJ Platform in a way -that is not as straightforward as adding an action to a menu or toolbar. +_Extensions_ are the most common way for a plugin to extend the IntelliJ Platform's functionality in a way that is not as straightforward as adding an action to a menu or toolbar. The following are some of the most common tasks accomplished using extensions: - * 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); * The `com.intellij.applicationConfigurable` and `com.intellij.projectConfigurable` extension points allow plugins to add pages to the [Settings/Preferences dialog](/basics/settings.md); * [Custom language plugins](/reference_guide/custom_language_support.md) use many extension points to extend various language support features in the IDE. -There are [more than 1000 extension](#how-to-get-the-extension-points-list) points available in the platform and the bundled plugins, allowing to customize -different parts of the IDE behavior. +There are [more than 1000 extension](#how-to-get-the-extension-points-list) points available in the platform and the bundled plugins, allowing to customize different parts of the IDE behavior. -## Declaring Extensions +## 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 `` 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 `` element to your `plugin.xml` if it's not yet present there. + Set the `defaultExtensionNs` attribute to one of the following values: * `com.intellij`, if your plugin extends the IntelliJ Platform core functionality. - * `{ID of a plugin}`, if your plugin extends a functionality of another plugin. -2. Add a new child element to the `` element. The child element name must match the name of the extension point you want the extension to access. + * `{ID of a plugin}`, if your plugin extends the functionality of another plugin. +2. Add a new child element to the `` element. + The child element name must match the name of the extension point you want the extension to access. 3. Depending on the type of the extension point, do one of the following: * If the extension point was declared using the `interface` attribute, for newly added child element, set the `implementation` attribute to the name of the class that implements the specified interface. * If the extension point was declared using the `beanClass` attribute, for newly added child element, set all attributes annotated with the [`@Attribute`](upsource:///platform/util/src/com/intellij/util/xmlb/annotations/Attribute.java) annotations in the specified bean class. @@ -45,11 +45,11 @@ To clarify this procedure, consider the following sample section of the `plugin. - ``` @@ -59,7 +59,7 @@ The following properties are available always: - `id` - unique ID - `order` - allows to order all defined extensions using `first`, `last` or `before|after [id]` respectively -- `os` - allows 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 @@ -85,13 +85,13 @@ Property name `language` (or ending in `*Language`, 2020.2+) resolves to all pre Similarly, `action` resolves to all registered `` IDs. -Specifying `@org.jetbrains.annotations.Nls` verifies capitalization of UI text properties according to given `capitalization` value (2019.2 and later). +Specifying `@org.jetbrains.annotations.Nls` validates a UI `String` capitalization according to the text property `Capitalization` enum value (2019.2 and later). Attributes with `Enum` type support code insight with _lowerSnakeCased_ notation (2020.1 and later). ## How to get the extension points list? -All available extension points for the specified namespace can be listed by using auto-completion inside `` block. +All available extension points for the specified namespace can be listed using auto-completion inside the `` block. To get a list of extension points available in the *IntelliJ Platform* core, consult the `` section of the following XML configuration files: @@ -102,4 +102,3 @@ To get a list of extension points available in the *IntelliJ Platform* core, con - [`EditorExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/EditorExtensionPoints.xml) - [`PlatformExtensionPoints.xml`](upsource:///platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml) - [`VcsExtensionPoints.xml`](upsource:///platform/vcs-impl/resources/META-INF/VcsExtensionPoints.xml) - diff --git a/basics/plugin_structure/plugin_icon_file.md b/basics/plugin_structure/plugin_icon_file.md index 41e66a36d..b57d9ed0e 100644 --- a/basics/plugin_structure/plugin_icon_file.md +++ b/basics/plugin_structure/plugin_icon_file.md @@ -5,17 +5,17 @@ title: Plugin 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. -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. * bullet list {:toc} ## Introduction -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. +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. Whether online or in the product UI, a Plugin Logo helps users to identify a plugin more quickly in a list, as shown below: ![Example Product Plugin Preferences Dialog](img/plugin_prefs.png){: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, * Be in the correct file format, * 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 -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: * 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. ### 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: ![36px by 36px is the area where the visible part of the Logo should fit](img/icon_size.png){:width="225px"} -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. -See more examples of [visual weight compensation](https://jetbrains.design/intellij/principles/icons/#08) in the IntelliJ Platform UI Guidelines for Icons. +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. +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. -Note the different areas of transparent padding used for each shape: +For basic shapes, use the following sizes. +Note the different areas of transparent padding used for each shape: | ![Square 32px by 32px](img/square_logo.png){:width="225px"} | ![Circle 36px in diameter](img/circle_logo.png){:width="225px"} | |:---:|:---:| @@ -57,38 +57,39 @@ Note the different areas of transparent padding used for each shape:
### Plugin Logo Colors -If the plugin’s technology already has a logo, use its colors. -Check the license terms before using the logo. +If the plugin's technology already has a logo, use its colors. +Check the license terms before using the logo. If there is no existing logo, or its use is prohibited, create a custom logo based on the [Action Colors Palette](https://jetbrains.design/intellij/principles/icons/#action-icons) in the IntelliJ Platform UI Guidelines for Icons. | ![The YouTrack Plugin Logo uses the YouTrack product logo ](img/yt_logo.png){:height="200px" width="200px"} | ![The Keymap Plugin Logo uses a color from the Action Colors Palette](img/keymap_logo.png){:height="200px" width="200px"} | |:---:|:---:| | _The YouTrack Plugin Logo uses
the YouTrack product logo_ | _The Keymap Plugin Logo uses a color
from the Action Colors Palette_ | -Ensure a Plugin Logo is visible on both light and dark backgrounds. -If one Plugin Logo design does not work on both light and dark backgrounds, then create separate light and dark versions of the Plugin Logo. -The examples below illustrate how a Plugin Logo design may work well for a light background but not so well for a dark background. -Consequently, a separate Plugin Logo for dark backgrounds is needed. +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, create separate light and dark versions of the Plugin Logo. +The examples below illustrate how a Plugin Logo design may work well for a light background but not for a dark background. +Consequently, a separate Plugin Logo for dark backgrounds is needed. | ![Plugin Logo on Light UI Theme](img/light_version.png){:width="225px"} | ![Light Plugin Logo on Dark UI Theme](img/dark_bad.png){:width="225px"} | ![Plugin Logo for Dark UI Theme](img/dark_good.png){:width="225px"} | |:---:|:---:|:---:| | _The light Plugin Logo design
works well on light UI Theme_ | _The light Plugin Logo design does
not work well on a dark UI Theme_ | _A separate, dark Plugin Logo design
works well on dark UI Theme_ | ### 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. ### Plugin Logo File Naming Convention Name the Plugin Logo files according to the following conventions: -* `pluginIcon.svg` is the default Plugin Logo. If a separate Logo file for dark UI Themes exists in the plugin, then this file is used solely for light UI Themes, +* `pluginIcon.svg` is the default Plugin Logo. + If a separate Logo file for dark UI Themes exists in the plugin, then this file is used solely for light UI Themes, * `pluginIcon_dark.svg` is an optional, alternative Plugin Logo for use solely with dark IDE UI Themes. - + ## Adding Plugin Logo Files to a Plugin Project -The Plugin Logo files must be in the `META-INF` folder of the plugin distribution file, i.e. the `*.jar` or `*.zip` file you upload to the plugin repository and install into a JetBrains IDE. +The Plugin Logo files must be in the `META-INF` folder of the plugin distribution file, i.e., the `*.jar` or `*.zip` file you upload to the plugin repository and install into a JetBrains IDE. + +To include Plugin Logo files in your distribution file, place the Plugin Logo files into a plugin project's `resources/META-INF` folder. +Note that this requirement is the same regardless of using DevKit or Gradle for developing a plugin. +For example: -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: - ![Plugin Logo Files in META-INF folder](img/resource_directory_structure.png){:width="450px"} - diff --git a/basics/plugin_structure/plugin_listeners.md b/basics/plugin_structure/plugin_listeners.md index e88de0a21..1a98bb85c 100644 --- a/basics/plugin_structure/plugin_listeners.md +++ b/basics/plugin_structure/plugin_listeners.md @@ -7,13 +7,12 @@ title: Plugin Listeners > **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. -Declarative registration of listeners allows you to achieve better performance compared to registering listeners -from code, because listener instances are created lazily (the first time an event is sent to the topic), and not -during application startup or project opening. +Declarative registration of listeners allows you to achieve better performance than registering listeners from code. +The advantage is because listener instances get created lazily - the first time an event is sent to the topic - and not during application startup or project opening. ## Defining Application-Level Listeners @@ -26,12 +25,10 @@ To define an application-level listener, add the following section to your `plug ``` The `topic` attribute specifies the listener interface corresponding to the type of events you want to receive. -Normally, this is the interface used as the type parameter of the [`Topic`](upsource:///platform/extensions/src/com/intellij/util/messages/Topic.java) instance for the type of events. -The `class` attribute specifies the class in your plugin that implements the listener interface and receives -the events. +Usually, this is the interface used as the type parameter of the [`Topic`](upsource:///platform/extensions/src/com/intellij/util/messages/Topic.java) instance for the type of events. +The `class` attribute specifies the class in your plugin that implements the listener interface and receives the events. -As a specific example, if you want to receive events about all changes in the virtual file system, you need -to implement the `BulkFileListener` interface, corresponding to the topic `VirtualFileManager.VFS_CHANGES`. +As a specific example, if you want to receive events about all virtual file system changes, you need to implement the `BulkFileListener` interface, corresponding to the topic `VirtualFileManager.VFS_CHANGES`. To subscribe to this topic from code, you could use something like the following snippet: ```java @@ -43,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 the listener interface class: +To use declarative registration, you no longer need to reference the `Topic` instance. +Instead, you refer directly to the listener interface class: ```xml - ``` @@ -66,18 +63,17 @@ public class MyVfsListener implements BulkFileListener { ## Defining Project-Level Listeners -Project-level listeners are registered in the same way, except that the top-level tag is -``. They can be used to listen to project-level events, for example, tool window operations: +Project-level listeners are registered in the same way, except that the top-level tag is ``. +They can be used to listen to project-level events, for example, tool window operations: ```xml - ``` -The class implementing the listener interface can define a one-argument constructor accepting a `Project`, -and it will receive the instance of the project for which the listener is created: +The class implementing the listener interface can define a one-argument constructor accepting a `Project`, and it will receive the instance of the project for which the listener is created: ```java public class MyToolwindowListener implements ToolWindowManagerListener { @@ -92,12 +88,13 @@ public class MyToolwindowListener implements ToolWindowManagerListener { // handle the state change } } -``` +``` ## Additional 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) -- `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. \ No newline at end of file +- `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. diff --git a/basics/plugin_structure/plugin_services.md b/basics/plugin_structure/plugin_services.md index 4dcaba36e..2a07b4528 100644 --- a/basics/plugin_structure/plugin_services.md +++ b/basics/plugin_structure/plugin_services.md @@ -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. -A service must have an implementation class which is used for service instantiation. -A service may also have an interface class which is used to obtain the service instance and provides API of the service. +A service must have an implementation class that is used for service instantiation. +A service may also have an interface class used to obtain the service instance and provide the service's API. A service needing a shutdown hook/cleanup routine can implement [`Disposable`](upsource:///platform/util/src/com/intellij/openapi/Disposable.java) and perform necessary work in `dispose()` (see [Automatically Disposed Objects](/basics/disposers.md#automatically-disposed-objects)). #### Types -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). +The *IntelliJ Platform* offers three types of services: _application level_ services (global singleton), _project level_ services, and _module level_ services. +For the latter two, a separate instance of the service is created for each instance of its corresponding scope, see [Project Model Introduction](/basics/project_structure.md). -> **NOTE** Please consider not using module level services because it can lead to increased memory usage for projects with many modules. +> **NOTE** Please consider not using module-level services because it can increase memory usage for projects with many modules. #### Constructor -Project/Module level service constructors can have `Project`/`Module` argument. +Project/Module level service constructors can have a `Project`/`Module` argument. To improve startup performance, avoid any heavy initializations in the constructor. -> **NOTE** Please note that using constructor injection is deprecated (and not supported in [Light Services](#light-services)) for performance reasons. Other dependencies should be [acquired only when needed](#retrieving-a-service) in all corresponding methods (see `someServiceMethod()` in [Project Service Sample](#project-service-sample)). +> **NOTE** Please note that using constructor injection is deprecated (and not supported in [Light Services](#light-services)) for performance reasons. +> Other dependencies should be [acquired only when needed](#retrieving-a-service) in all corresponding methods (see `someServiceMethod()` in [Project Service Sample](#project-service-sample)). ## Light Services > **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)). -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)). - +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 the caller (see [Retrieving a Service](#retrieving-a-service)). + Restrictions: * Service class must be `final`. * 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`). -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 @@ -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. 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: ```xml - - ``` @@ -76,7 +77,8 @@ To provide custom implementation for test/headless environment, specify `testSer ## Retrieving a Service -Getting service doesn't need read action and can be performed from any thread. If service is requested from several threads, it will be initialized in the first thread, and other threads will be blocked until service is fully initialized. +Getting service doesn't need a read action and can be performed from any thread. +If service is requested from several threads, it will be initialized in the first thread, and other threads will be blocked until service is fully initialized. To retrieve a service in Java code: @@ -99,7 +101,7 @@ This minimal sample shows [light](#light-services) `ProjectService` interacting _ProjectService.java_ -```java +```java @Service public final class ProjectService { @@ -107,10 +109,10 @@ _ProjectService.java_ public ProjectService(Project project) { myProject = project; - } + } public void someServiceMethod(String parameter) { - AnotherService anotherService = myProject.getService(AnotherService.class); + AnotherService anotherService = myProject.getService(AnotherService.class); String result = anotherService.anotherServiceMethod(parameter, false); // do some more stuff } @@ -119,7 +121,9 @@ _ProjectService.java_ ## Sample Plugin -This sample plugin illustrates how to create and use a plugin service. This plugin has an application service counting the number of currently opened projects in the IDE. If this number exceeds the maximum allowed number of simultaneously opened projects, the plugin displays a warning message. +This sample plugin illustrates how to create and use a plugin service. +This plugin has an application service counting the number of currently opened projects in the IDE. +If this number exceeds the maximum number of simultaneously opened projects allowed by the plugin, it displays a warning message. **To install and run the sample plugin** diff --git a/basics/project_structure.md b/basics/project_structure.md index c3650aa67..5e21471e5 100644 --- a/basics/project_structure.md +++ b/basics/project_structure.md @@ -5,50 +5,52 @@ title: Project Structure -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. * bullet list {:toc} ## Project and Its Components -This section briefly discusses the IDEA project structure, project components and related terms. +This section briefly discusses the IDEA project structure, project components, and related terms. For more information about projects and their components, refer to [Project](https://www.jetbrains.com/help/idea/about-projects.html), [Module](https://www.jetbrains.com/help/idea/creating-and-managing-modules.html), [Library](https://www.jetbrains.com/help/idea/working-with-libraries.html), [Facet](https://www.jetbrains.com/help/idea/adding-support-for-frameworks-and-technologies.html#facets) in the IntelliJ IDEA Web Help. ### Project -In the IntelliJ Platform, a _project_ encapsulates all of a project's source code, libraries, and build instructions into a single organizational unit. -Everything done using the IntelliJ Platform SDK is done within the context of a project. -A project defines collections referred to as _modules_ and _libraries_. -Depending on the logical and functional requirements for the project, you can create a _single-module_ or a _multi-module_ project. +In the IntelliJ Platform, a _project_ encapsulates all of a project's source code, libraries, and build instructions into a single organizational unit. +Everything done using the IntelliJ Platform SDK is done within the context of a project. +A project defines collections referred to as _modules_ and _libraries_. +Depending on the project's logical and functional requirements, you can create a _single-module_ or a _multi-module_ project. ### Module -A _module_ is a discrete unit of functionality that can be run, tested, and debugged independently. -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). +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. +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. ### 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: -* **Module Library**: the library classes are visible only in this module and the library information is recorded in the module's `.iml` file. -* **Project Library**: the library classes are visible within the project and the library information is recorded in the project's `.ipr` file or in `.idea/libraries`. -* **Global Library**: the library information is recorded in the `applicationLibraries.xml` file in the `~/.IntelliJIdea/config/options` directory. Global libraries are similar to project libraries, but are visible for different projects. +* **Module Library**: the library classes are visible only in this module, and the library information is recorded in the module's `.iml` file. +* **Project Library**: the library classes are visible within the project, and the library information is recorded in the project's `.ipr` file or in `.idea/libraries`. +* **Global Library**: the library information is recorded in the `applicationLibraries.xml` file in the `~/.IntelliJIdea/config/options` directory. + Global libraries are similar to project libraries but are visible for different projects. For more information about libraries, refer to [Library](https://www.jetbrains.com/help/idea/working-with-libraries.html). ### SDK -Every project uses a Software Development Kit (_SDK_). For Java projects, SDK is referred to as JDK (Java Development Kit). +Every project uses a Software Development Kit (_SDK_). +For Java projects, SDK is referred to as JDK (Java Development Kit). -The SDK determines which API library is used to build the project. +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. 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. ### Facet -A _facet_ represents a certain configuration, specific for a particular framework/technology associated with a module. -A module can have multiple facets. -E.g. Spring specific configuration is stored in a Spring facet. +A _facet_ represents a certain configuration, specific for a particular framework/technology associated with a module. +A module can have multiple facets. +E.g., Spring-specific configuration is stored in a Spring facet. 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. diff --git a/basics/psi_cookbook.md b/basics/psi_cookbook.md index b792a31d3..77ad9298a 100644 --- a/basics/psi_cookbook.md +++ b/basics/psi_cookbook.md @@ -3,7 +3,8 @@ title: PSI Cookbook --- -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). @@ -46,7 +47,7 @@ This page gives a list of recipes for the most common operations for working wit ```java PsiJavaFile javaFile = (PsiJavaFile) psiClass.getContainingFile(); PsiPackage pkg = JavaPsiFacade.getInstance(project).findPackage(javaFile.getPackageName()); -``` +``` or diff --git a/basics/run_configurations.md b/basics/run_configurations.md index 64ce81b34..b47384124 100644 --- a/basics/run_configurations.md +++ b/basics/run_configurations.md @@ -3,13 +3,15 @@ title: Run Configurations --- -*Run Configurations* allow users to run a certain type of external processes from within the IDE, e.g. a script, an application, a server, etc. You can provide UI for the user to specify execution options, as well as an option to create a run configuration based on a specific location in the source code. +*Run Configurations* allow users to run specific external processes from within the IDE, e.g., a script, an application, a server, etc. +You can provide the UI for the user to specify execution options, and an option to create a run configuration based on a specific location in the source code. ## Architectural Overview Classes used to manipulate run configurations can be split into the following groups: -* [Run configuration management](/basics/run_configurations/run_configuration_management.md). This includes creation, persistence, and modification. +* [Run configuration management](/basics/run_configurations/run_configuration_management.md). + This includes creation, persistence, and modification. * [Execution](/basics/run_configurations/run_configuration_execution.md). This diagram shows the main classes: diff --git a/basics/run_configurations/run_configuration_execution.md b/basics/run_configurations/run_configuration_execution.md index 249a887d6..733b32ed0 100644 --- a/basics/run_configurations/run_configuration_execution.md +++ b/basics/run_configurations/run_configuration_execution.md @@ -6,47 +6,62 @@ title: Execution The standard execution of a run action goes through the following steps: * The user selects a *run configuration* (for example, by choosing one from the run configurations combobox) and an *executor* (for example, by pressing a toolbar button created by the executor). -* The *program runner* that will actually execute the process is selected, by polling all registered program runners and asking whether they can run the specified run profile with the specified executor ID. -* The [`ExecutionEnvironment`](upsource:///platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java) object is created. This object aggregates all the settings required to execute the process, as well as the selected [`ProgramRunner`](upsource:///platform/lang-api/src/com/intellij/execution/runners/ProgramRunner.java). +* The *program runner* that will actually execute the process is selected by polling all registered program runners and asking whether they can run the specified run profile with the specified executor ID. +* The [`ExecutionEnvironment`](upsource:///platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java) object is created. + This object aggregates all the settings required to execute the process and the selected [`ProgramRunner`](upsource:///platform/lang-api/src/com/intellij/execution/runners/ProgramRunner.java). * `ProgramRunner.execute()` is called, receiving the executor and the execution environment. Implementations of `ProgramRunner.execute()` go through the following steps to execute the process: -* `RunProfile.getState()` method is called to create a [`RunProfileState`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunProfileState.java) object, describing a process about to be started. At this stage, the command line parameters, environment variables and other information required to start the process is initialized. -* `RunProfileState.execute()` is called. It starts the process, attaches a `ProcessHandler` to its input and output streams, creates a console to display the process output, and returns an [`ExecutionResult`](upsource:///platform/lang-api/src/com/intellij/execution/ExecutionResult.java) object aggregating the console and the process handler. +* `RunProfile.getState()` method is called to create a [`RunProfileState`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunProfileState.java) object, describing a process about to be started. + At this stage, the command line parameters, environment variables, and other information required to start the process are initialized. +* `RunProfileState.execute()` is called. + It starts the process, attaches a `ProcessHandler` to its input and output streams, creates a console to display the process output, and returns an [`ExecutionResult`](upsource:///platform/lang-api/src/com/intellij/execution/ExecutionResult.java) object aggregating the console and the process handler. * The `RunContentBuilder` object is created and invoked to display the execution console in a tab of the Run or Debug tool window. ## Executor The [`Executor`](upsource:///platform/lang-api/src/com/intellij/execution/Executor.java) interface describes a specific way of executing any possible run configuration. -The three default executors provided by the *IntelliJ Platform* by default are _Run_, _Debug_ and _Run with Coverage_. Each executor gets its own toolbar button, which starts the selected run configuration using this executor, and its own context menu item for starting a configuration using this executor. +The three default executors provided by the *IntelliJ Platform* by default are _Run_, _Debug_, and _Run with Coverage_. Each executor gets its own toolbar button, which starts the selected run configuration using this executor, and its own context menu item for starting a configuration using this executor. -As a plugin developer, you normally don't need to implement the `Executor` interface. However, it can be useful, for example, if you're implementing a profiler integration and want to provide the possibility to execute any configuration with profiling. +As a plugin developer, you usually don't need to implement the `Executor` interface. +However, it can be useful, for example, if you're implementing a profiler integration and want to provide the possibility to execute any configuration with profiling. ## Running a Process -The `RunProfileState` interface comes up in every run configuration implementation as the return value `RunProfile.getState()`. It describes a process which is ready to be started and holds the information like the command line, current working directory, and environment variables for the process to be started. (The existence of `RunProfileState` as a separate step in the execution flow allows run configuration extensions and other components to patch the configuration and to modify the parameters before it gets executed.) +The `RunProfileState` interface comes up in every run configuration implementation as the return value `RunProfile.getState()`. +It describes a process that is ready to be started and holds information like the command line, current working directory, and environment variables for the process to be started. (The existence of `RunProfileState` as a separate step in the execution flow allows run configuration extensions and other components to patch the configuration and modify the parameters before it gets executed.) -The standard base class used as implementation of `RunProfileState` is [`CommandLineState`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java). It contains the logic for putting together a running process and a console into an [`ExecutionResult`](upsource:///platform/lang-api/src/com/intellij/execution/ExecutionResult.java), but doesn't know anything how the process is actually started. For starting the process, it's best to use the [`GeneralCommandLine`](upsource:///platform/platform-util-io/src/com/intellij/execution/configurations/GeneralCommandLine.java) class, which takes care of setting up the command line parameters and executing the process. +The standard base class used as implementation of `RunProfileState` is [`CommandLineState`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java). +It contains the logic for putting together a running process and a console into an [`ExecutionResult`](upsource:///platform/lang-api/src/com/intellij/execution/ExecutionResult.java), but doesn't know anything how the process is actually started. +For starting the process, it's best to use the [`GeneralCommandLine`](upsource:///platform/platform-util-io/src/com/intellij/execution/configurations/GeneralCommandLine.java) class, which takes care of setting up the command line parameters and executing the process. -Alternatively, if the process you need to run is a JVM-based one, you can use the [`JavaCommandLineState`](upsource:///java/execution/openapi/src/com/intellij/execution/configurations/JavaCommandLineState.java) base class. It knows about the command line parameters of the JVM and can take care of details like calculating the classpath for the JVM. +Alternatively, if the process you need to run is a JVM-based one, you can use the [`JavaCommandLineState`](upsource:///java/execution/openapi/src/com/intellij/execution/configurations/JavaCommandLineState.java) base class. +It knows about the JVM command line parameters and can take care of details like calculating the classpath for the JVM. -To monitor the execution of a process and capture its output, the [`OSProcessHandler`](upsource:///platform/platform-util-io/src/com/intellij/execution/process/OSProcessHandler.java) class is normally used. Once you've created an instance of `OSProcessHandler` from either a command line or a Process object, you need to call the `startNotify()` method to start capturing its output. You may also want to attach a [`ProcessTerminatedListener`](upsource:///platform/platform-api/src/com/intellij/execution/process/ProcessTerminatedListener.java) to the `OSProcessHandler`, so that the exit status of the process will be displayed in the console. +To monitor the execution of a process and capture its output, the [`OSProcessHandler`](upsource:///platform/platform-util-io/src/com/intellij/execution/process/OSProcessHandler.java) class is usually used. +Once you've created an instance of `OSProcessHandler` from either a command line or a Process object, you need to call the `startNotify()` method to capture its output. +You may also want to attach a [`ProcessTerminatedListener`](upsource:///platform/platform-api/src/com/intellij/execution/process/ProcessTerminatedListener.java) to the `OSProcessHandler` so that the exit status of the process will be displayed in the console. ## Displaying Process Output -If you're using `CommandLineState`, a console view will be automatically created and attached to the output of the process. Alternatively, you can arrange this yourself: +If you're using `CommandLineState`, a console view will be automatically created and attached to the process's output. +Alternatively, you can arrange this yourself: * `TextConsoleBuilderFactory.createBuilder(project).getConsole()` creates a [`ConsoleView`](upsource:///platform/lang-api/src/com/intellij/execution/ui/ConsoleView.java) instance * `ConsoleView.attachToProcess()` attaches it to the output of a process. -If the process you're running uses ANSI escape codes to color its output, the [`ColoredProcessHandler`](upsource:///platform/platform-impl/src/com/intellij/execution/process/ColoredProcessHandler.java) class will parse it and display the colors in the IntelliJ console. +If the running process uses ANSI escape codes to color its output, the [`ColoredProcessHandler`](upsource:///platform/platform-impl/src/com/intellij/execution/process/ColoredProcessHandler.java) class will parse it and display the colors in the IntelliJ console. -Console [filters](upsource:///platform/lang-api/src/com/intellij/execution/filters/Filter.java) allow you to convert certain strings found in the process output to clickable hyperlinks. To attach a filter to the console, use `CommandLineState.addConsoleFilters()` or, if you're creating a console manually, `TextConsoleBuilder.addFilter()`. +Console [filters](upsource:///platform/lang-api/src/com/intellij/execution/filters/Filter.java) allow you to convert certain strings found in the process output to clickable hyperlinks. +To attach a filter to the console, use `CommandLineState.addConsoleFilters()` or, if you're creating a console manually, `TextConsoleBuilder.addFilter()`. Two common filter implementations you may want to reuse are [`RegexpFilter`](upsource:///platform/lang-api/src/com/intellij/execution/filters/RegexpFilter.java) and [`UrlFilter`](upsource:///platform/lang-api/src/com/intellij/execution/filters/UrlFilter.java). ## Starting a Run Configuration from Code -If you have an existing run configuration that you need to execute, the easiest way to do so is to use [`ProgramRunnerUtil.executeConfiguration()`](upsource:///platform/execution-impl/src/com/intellij/execution/ProgramRunnerUtil.java). The method takes a [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java), a [`RunnerAndConfigurationSettings`](upsource:///platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java), as well as an [`Executor`](upsource:///platform/lang-api/src/com/intellij/execution/Executor.java). To get the `RunnerAndConfigurationSettings` for an existing configuration, you can use, for example, `RunManager.getConfigurationSettings(ConfigurationType)`. As the last parameter, you normally pass either `DefaultRunExecutor.getRunExecutorInstance()` or `DefaultDebugExecutor.getDebugExecutorInstance()`. +If you have an existing run configuration that you need to execute, the easiest way to do so is to use [`ProgramRunnerUtil.executeConfiguration()`](upsource:///platform/execution-impl/src/com/intellij/execution/ProgramRunnerUtil.java). +The method takes a [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java), a [`RunnerAndConfigurationSettings`](upsource:///platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java), as well as an [`Executor`](upsource:///platform/lang-api/src/com/intellij/execution/Executor.java). +To get the `RunnerAndConfigurationSettings` for an existing configuration, you can use, for example, `RunManager.getConfigurationSettings(ConfigurationType)`. +As the last parameter, you normally pass either `DefaultRunExecutor.getRunExecutorInstance()` or `DefaultDebugExecutor.getDebugExecutorInstance()`. diff --git a/basics/run_configurations/run_configuration_management.md b/basics/run_configurations/run_configuration_management.md index bdb47e04f..54d4d4853 100644 --- a/basics/run_configurations/run_configuration_management.md +++ b/basics/run_configurations/run_configuration_management.md @@ -3,14 +3,15 @@ title: Run Configuration Management --- -This document describes main classes to work with run configurations and common use case. +This document describes the primary classes to work with run configurations and everyday use cases. * Dummy table of contents {:toc} ## Configuration Type -The starting point for implementing any run configuration type is the [`ConfigurationType`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationType.java) interface. The list of available configuration types is shown when a user opens the _'Edit run configurations'_ dialog and executes _'Add'_ action: +The starting point for implementing any run configuration type is the [`ConfigurationType`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationType.java) interface. +The list of available configuration types is shown when a user opens the _'Edit run configurations'_ dialog and executes _'Add'_ action: ![Create](/basics/img/create-1.png) @@ -20,39 +21,47 @@ Every type there is represented as an instance of [`ConfigurationType`](upsource ``` -The easiest way to implement this interface is to use the [`ConfigurationTypeBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/runConfigurationType.kt) base class. In order to use it, you need to inherit from it and to provide the configuration type parameters (ID, name, description and icon) as constructor parameters. In addition to that, you need to call the [`addFactory()`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/runConfigurationType.kt) method to add a configuration factory. +The easiest way to implement this interface is to use the [`ConfigurationTypeBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/runConfigurationType.kt) base class. +To use it, you need to inherit from it and to provide the configuration type parameters (ID, name, description, and icon) as constructor parameters. +In addition to that, you need to call the [`addFactory()`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/runConfigurationType.kt) method to add a configuration factory. ## Configuration Factory -All run configurations are created by the [`ConfigurationFactory`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) registered for a particular `ConfigurationType`. It's possible that one `ConfigurationType` [has more than one](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationType.java) `ConfigurationFactory`: +All run configurations are created by the [`ConfigurationFactory`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) registered for a particular `ConfigurationType`. +It's possible that one `ConfigurationType` [has more than one](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationType.java) `ConfigurationFactory`: ![Configuration Factory](/basics/img/create-3.png) -The key API of [`ConfigurationFactory`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java), and the only method that you're required to implement, is the [`createTemplateConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) method. This method is called once per project to create the template run configuration. +The key API of [`ConfigurationFactory`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java), and the only method that you're required to implement, is the [`createTemplateConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) method. +This method is called once per project to create the template run configuration. All real run configurations (loaded from the workspace or created by the user) are called by cloning the template through the [`createConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) method. -You can customize additional aspects of your configuration factory by overriding the [`getIcon`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java), [`getAddIcon`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java), [`getName`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) 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), [`getName`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) and the default settings methods. +These additional overrides are optional. ## Run Configuration -The run configuration itself is represented by the [`RunConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java) interface. A _'run configuration'_ here is some named profile which can be executed, e.g. application started via `main()` class, test, remote debug to particular machine/port etc. +The run configuration itself is represented by the [`RunConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java) interface. +A _'run configuration'_ here is some named profile which can be executed, e.g., the application started via `main()` class, test, remote debug to particular machine/port, etc. -Here is an example of a Java run configurations defined for a particular project: +Here is an example of a Java run configuration defined for a particular project: ![Run Configuration](/basics/img/create-2.png) When implementing a run configuration, you may want to use one of the common base classes: * [`RunConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java) is a general-purpose superclass that contains the most basic implementation of a run configuration. -* [`LocatableConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/LocatableConfigurationBase.java) is a common base class that should be used for configurations that can be created from context by a `RunConfigurationProducer`. It supports automatically generating a name for a configuration from its settings and keeping track of whether the name was changed by the user. +* [`LocatableConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/LocatableConfigurationBase.java) is a common base class that should be used for configurations that can be created from context by a `RunConfigurationProducer`. + It supports automatically generating a name for a configuration from its settings and keeping track of whether the name was changed by the user. * [`ModuleBasedConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ModuleBasedConfiguration.java) is a base class for a configuration that is associated with a specific module (for example, Java run configurations use the selected module to determine the run classpath). ## Settings Editor That common run configuration settings might be modified via: -[`RunConfiguration`-specific UI](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java). That is handled by [`SettingsEditor`](upsource:///platform/platform-api/src/com/intellij/openapi/options/SettingsEditor.java): +[`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): * [`getComponent()`](upsource:///platform/platform-api/src/com/intellij/openapi/options/SettingsEditor.java) method is called by the IDE and shows run configuration specific UI. * [`resetFrom()`](upsource:///platform/platform-api/src/com/intellij/openapi/options/SettingsEditor.java) is called to discard all non-confirmed user changes made via that UI. @@ -60,35 +69,41 @@ That common run configuration settings might be modified via: ## Persistence -That run configuration settings are persistent, i.e. they are stored at file system and loaded back on the IDE startup. That is performed via [`writeExternal()`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) and [`readExternal()`](upsource:///platform/util/src/com/intellij/openapi/util/JDOMExternalizable.java) 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) methods of [`RunConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java) class correspondingly. The actual configurations stored by the *IntelliJ Platform* are represented by instances of the [`RunnerAndConfigurationSettings`](upsource:///platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java) class, which combines a run configuration with runner-specific settings, as well as keeping track of certain run configuration flags such as "temporary" or "singleton". -Dealing with instances of this class becomes necessary when you need to create run configurations from code. This is accomplished with the following two steps: +Dealing with instances of this class becomes necessary when you need to create run configurations from code. +This is accomplished with the following two steps: * `RunManager.createConfiguration()` creates an instance of `RunnerAndConfigurationSettings`. -* `RunManager.addConfiguration()` makes it persistent by adding it to either the list of shared configurations stored in a project, or to the list of local configurations stored in the workspace file. +* `RunManager.addConfiguration()` makes it persistent by adding it to either the list of shared configurations stored in a project or to the list of local configurations stored in the workspace file. ## Refactoring Support -Most run configurations contain references to classes, files or directories in their settings, and these settings usually need to be updated when the corresponding element is renamed or moved. +Most run configurations contain references to classes, files, or directories in their settings, and these settings usually need to be updated when the corresponding element is renamed or moved. -In order to support that, your run configuration needs to implement the [`RefactoringListenerProvider`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RefactoringListenerProvider.java) interface. +To support that, your run configuration needs to implement the [`RefactoringListenerProvider`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RefactoringListenerProvider.java) interface. -In your implementation of `getRefactoringElementListener()`, you need to check whether the element being refactored is the one that your run configuration refers to, and if it is, you return a [`RefactoringElementListener`](upsource:///platform/analysis-api/src/com/intellij/refactoring/listeners/RefactoringElementListener.java) that updates your configuration according to the new name and location of the element. +In your implementation of `getRefactoringElementListener()`, you need to check whether the refactored element is the one that your run configuration refers to. +If it is, you return a [`RefactoringElementListener`](upsource:///platform/analysis-api/src/com/intellij/refactoring/listeners/RefactoringElementListener.java) that updates your configuration according to the new name and location of the element. ## Creating Configurations from Context -Many plugins support automatic creation of run configurations from context, so that the user can click, for example, on an application or test class and automatically run it using the correct run configuration type. In order to support that, you need to provide an implementation of the [`RunConfigurationProducer`](upsource:///platform/lang-api/src/com/intellij/execution/actions/RunConfigurationProducer.java) -interface and to register it as `` in your `plugin.xml`. (Note that this API has been redesigned in IntelliJ IDEA 13; the old [`RuntimeConfigurationProducer`](upsource:///platform/lang-api/src/com/intellij/execution/junit/RuntimeConfigurationProducer.java) is a much more confusing version of the same API). +Many plugins support automatic creation of run configurations from context so that the user can click, for example, on an application or test class and automatically run it using the correct run configuration type. +To support that, you need to provide an implementation of the [`RunConfigurationProducer`](upsource:///platform/lang-api/src/com/intellij/execution/actions/RunConfigurationProducer.java) interface and to register it as `` in your `plugin.xml`. +This API was redesigned in IntelliJ IDEA 13; the previous [`RuntimeConfigurationProducer`](upsource:///platform/lang-api/src/com/intellij/execution/junit/RuntimeConfigurationProducer.java) is a much more confusing version of the same API. The two main methods that you need to implement are: -* `setupConfigurationFromContext()` receives a blank configuration of your type and a `ConfigurationContext` containing information about a source code location (accessible by calling `getLocation()` or `getPsiLocation()`). Your implementation needs to check whether the location is applicable for your configuration type (for example, if it's in a file of the language you're supporting). If not, you need to return false, and if it is, you need to put the correct context-specific settings into the run configuration and return true. -* `isConfigurationFromContext()` checks if the specified configuration of your type was created from the specified context. Implementing this method allows you to reuse an existing run configuration which is applicable to the current context instead of creating a new one and possibly ignoring the customisations the user has performed in the existing one. +* `setupConfigurationFromContext()` receives a blank configuration of your type and a `ConfigurationContext` containing information about a source code location (accessible by calling `getLocation()` or `getPsiLocation()`). + Your implementation needs to check whether the location is applicable for your configuration type (for example, if it's in a file of the language you're supporting). + If not, you need to return false, and if it is, you need to put the correct context-specific settings into the run configuration and return true. +* `isConfigurationFromContext()` checks if your type's specified configuration was created from the specified context. + Implementing this method allows you to reuse an existing run configuration, which applies to the current context instead of creating a new one and possibly ignoring the user's customizations in the existing one. -Note that, in order to support automatic naming of configurations created from context, your configuration should use -[`LocatableConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/LocatableConfigurationBase.java) as the base class. +Note that, to support the automatic naming of configurations created from context, your configuration should use [`LocatableConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/LocatableConfigurationBase.java) as the base class. ## Running from the Gutter diff --git a/basics/settings.md b/basics/settings.md index af3d64c2e..bd96b859f 100644 --- a/basics/settings.md +++ b/basics/settings.md @@ -9,4 +9,3 @@ For more information, see: * [Settings Guide](/reference_guide/settings_guide.md) for information about Settings Extension Points and implementations. * [Custom Settings Groups](/reference_guide/settings_groups.md) for information about creating custom Settings groups and parent-child relationships. * [Settings Tutorial](/tutorials/settings_tutorial.md) for step-by-step instructions for creating a simple set of custom Settings. - diff --git a/basics/testing_plugins/light_and_heavy_tests.md b/basics/testing_plugins/light_and_heavy_tests.md index b0bfe9031..a10e19fb9 100644 --- a/basics/testing_plugins/light_and_heavy_tests.md +++ b/basics/testing_plugins/light_and_heavy_tests.md @@ -3,10 +3,11 @@ title: Light and Heavy Tests --- -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. * *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. -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`). ## 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. diff --git a/basics/testing_plugins/test_project_and_testdata_directories.md b/basics/testing_plugins/test_project_and_testdata_directories.md index 322b019c5..fe42e3986 100644 --- a/basics/testing_plugins/test_project_and_testdata_directories.md +++ b/basics/testing_plugins/test_project_and_testdata_directories.md @@ -3,33 +3,44 @@ title: Test Project and Testdata Directories --- -The test fixture creates a *test project* environment. Unless you customize the project creation, the test project will have one module with one source root called `src`. The files for the test project exist either in a temporary directory or in an in-memory file system, depending on which implementation of [`TempDirTestFixture`](upsource:///platform/testFramework/src/com/intellij/testFramework/fixtures/TempDirTestFixture.java) is used. +The test fixture creates a *test project* environment. +Unless you customize the project creation, the test project will have one module with one source root called `src`. +The test project files exist either in a temporary directory or in an in-memory file system, depending on which implementation of [`TempDirTestFixture`](upsource:///platform/testFramework/src/com/intellij/testFramework/fixtures/TempDirTestFixture.java) is used. [`LightPlatformCodeInsightFixtureTestCase`](upsource:///platform/testFramework/src/com/intellij/testFramework/fixtures/LightPlatformCodeInsightFixtureTestCase.java) (renamed to `BasePlatformTestCase` in 2019.2) uses an in-memory implementation; if you set up the test environment by calling `IdeaTestFixtureFactory.createCodeInsightFixture()`, you can specify the implementation to use. > **WARNING** If your tests use the in-memory implementation, and you abort the execution of your tests, the persisted filesystem caches may get out of sync with the in-memory structures, and you may get spurious errors in your tests. > If you get an unexpected error after a series of successful runs, **try rerunning the test**, and if that doesn't help, **delete the "system" subdirectory** in your [sandbox directory](/basics/ide_development_instance.md#the-development-instance-sandbox-directory). -In your plugin, you normally store the test data for your tests (such as files on which plugin features will be executed and expected output files) in the `testdata` directory. This is just a directory under the content root of your plugin, but not under a source root. Files in `testdata` usually are not valid source code and must not be compiled. +In your plugin, you usually store the test data for your tests (such as files on which plugin features will be executed and expected output files) in the `testdata` directory. +This is just a directory under your plugin's content root, but not under a source root. +Files in `testdata` usually are not valid source code and must not be compiled. -To specify the location of `testdata`, you must override the `getTestDataPath()` method. The default implementation assumes running as part of the *IntelliJ Platform* source tree and is not appropriate for third-party plugins. +To specify the location of `testdata`, you must override the `getTestDataPath()` method. +The default implementation assumes running as part of the *IntelliJ Platform* source tree and is not appropriate for third-party plugins. -> **NOTE** A very common pattern in *IntelliJ Platform* tests is to use the name of the test method being executed as the base for building the `testdata` file paths. This allows to reuse most of the code between different test methods that test different aspects of the same feature, and this approach is also recommended for third-party plugin tests. The name of the test method can be retrieved using `UsefulTestCase.getTestName()`. +> **NOTE** A very common pattern in *IntelliJ Platform* tests is to use the test method's name being executed as the base for building the `testdata` file paths. +> This allows us to reuse most of the code between different test methods that test various aspects of the same feature, and this approach is also recommended for third-party plugin tests. +> The name of the test method can be retrieved using `UsefulTestCase.getTestName()`. > **NOTE** If your plugin builds on top of Java support, please see [Tests Prerequisites](/tutorials/writing_tests_for_plugins/tests_prerequisites.md) for setting up your test environment to obtain required _Mock JDK_ automatically. To copy files or directories from your `testdata` directory to the test project directory, you can use the `copyFileToProject()` and `copyDirectoryToProject()` methods in the [`CodeInsightTestFixture`](upsource:///platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java) class. -Most operations in plugin tests require a file open in the in-memory editor, in which highlighting, completion and other operations will be performed. The in-memory editor instance is returned by `CodeInsightTestFixture.getEditor()`. To copy a file from the `testdata` directory to the test project directory and immediately open it in the editor, you can use the `CodeInsightTestFixture.configureByFile()` or `configureByFiles()` methods. The latter copies multiple files to the test project directory and opens the *first* of them in the in-memory editor. +Most operations in plugin tests require a file open in the in-memory editor, in which highlighting, completion, and other operations will be performed. +The in-memory editor instance is returned by `CodeInsightTestFixture.getEditor()`. +To copy a file from the `testdata` directory to the test project directory and immediately open it in the editor, you can use the `CodeInsightTestFixture.configureByFile()` or `configureByFiles()` methods. +The latter copies multiple files to the test project directory and opens the *first* of them in the in-memory editor. -Alternatively, you can use one of the other methods which take parameters annotated with [`@TestDataFile`](upsource:///platform/testFramework/src/com/intellij/testFramework/TestDataFile.java). These methods copy the specified files from the `testdata` directory to the test project directory, open the first of the specified files in the in-memory editor, and then perform the requested operation such as highlighting or code completion. +Alternatively, you can use one of the other methods which take parameters annotated with [`@TestDataFile`](upsource:///platform/testFramework/src/com/intellij/testFramework/TestDataFile.java). +These methods copy the specified files from the `testdata` directory to the test project directory, open the first of the specified files in the in-memory editor, and then perform the requested operation such as highlighting or code completion. -> **TIP** The IDE supports smart navigation between test code and related test data file(s), see this [blog post](https://blog.jetbrains.com/platform/2017/10/improvements-in-testing-intellij-platform-plugins/) for more details. +> **TIP** The IDE supports smart navigation between test code and related test data file(s); see this [blog post](https://blog.jetbrains.com/platform/2017/10/improvements-in-testing-intellij-platform-plugins/) for more details. ### Special Markup -When a file is opened in the in-memory editor, special markup in the file content can be used to specify the caret position or selection. +When a file is opened in the in-memory editor, special markup in the file content can specify the caret position or selection. You can use one of the following markers: * `` specifies the position where the caret should be placed. -* `` and `` specify the start and end of the text range to be selected. -* `` and `` specify the start and end points of the column selection. +* `` and `` specify the start and end of the selected text range. +* `` and `` specify the column selection's start and end points. diff --git a/basics/testing_plugins/testing_highlighting.md b/basics/testing_plugins/testing_highlighting.md index d4626849e..5e1778bbd 100644 --- a/basics/testing_plugins/testing_highlighting.md +++ b/basics/testing_plugins/testing_highlighting.md @@ -3,13 +3,19 @@ title: Testing Highlighting --- -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 code to be highlighted @@ -23,7 +29,8 @@ public int /buildUML` or, if you have the IntelliJ-Community source code, `//platform/docs/`. +* 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. +* 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. + 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: + * 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, `//buildUML` or, if you have the IntelliJ-Community source code, `//platform/docs/`. * 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. -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. diff --git a/code_samples/CODE_OF_CONDUCT.md b/code_samples/CODE_OF_CONDUCT.md index 1eacc476f..e34225dd9 100644 --- a/code_samples/CODE_OF_CONDUCT.md +++ b/code_samples/CODE_OF_CONDUCT.md @@ -1,3 +1,4 @@ ## Code of Conduct -This project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct). Please make sure you read it. +This project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct). +Please make sure you read it. diff --git a/code_samples/README.md b/code_samples/README.md index 11e27abe8..89568fe7a 100644 --- a/code_samples/README.md +++ b/code_samples/README.md @@ -6,8 +6,8 @@ [![Build](https://github.com/JetBrains/intellij-sdk-docs/workflows/Build/badge.svg)][gh:build] [![Slack](https://img.shields.io/badge/Slack-%23intellij--platform-blue)][jb:slack] -Learn how to build plugins using IntelliJ Platform SDK for the [JetBrains products][jb:products] by experimenting with -our code samples. These samples show you how features work and help you jumpstart your plugins. +Learn how to build plugins using IntelliJ Platform SDK for the [JetBrains products][jb:products] by experimenting with our code samples. +These samples show you how features work and help you jumpstart your plugins. There is also [IntelliJ Platform Plugin Template][gh:template] project available. @@ -20,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. -The main plugin definition file is stored in the `plugin.xml` file, which is created according -to the [Plugin Configuration File documentation][docs:plugin.xml]. It describes definitions of the actions, extensions, -or listeners provided by the plugin. +The main plugin definition file is stored in the `plugin.xml` file, which is created according to the [Plugin Configuration File documentation][docs:plugin.xml]. +It describes definitions of the actions, extensions, or listeners provided by the plugin. ## Code Samples -In the following table, you may find all available samples provided in the separated directories as stand-alone -projects available for running with the Gradle `:runIde` task. - +In the following table, you may find all available samples provided in the separated directories as stand-alone projects available for running with the Gradle `:runIde` task. + | Code Sample | Description | | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | [Action Basics](./action_basics) | Action and Action Group patterns implementation, adds entries to the Tools menu. | diff --git a/code_samples/_gradleCompositeBuild/settings.gradle b/code_samples/_gradleCompositeBuild/settings.gradle index c808bb520..390af402e 100644 --- a/code_samples/_gradleCompositeBuild/settings.gradle +++ b/code_samples/_gradleCompositeBuild/settings.gradle @@ -24,4 +24,3 @@ includeBuild '../settings' includeBuild '../simple_language_plugin' includeBuild '../tool_window' includeBuild '../tree_structure_provider' - diff --git a/code_samples/action_basics/README.md b/code_samples/action_basics/README.md index 85d2dc7f8..a428bf23f 100644 --- a/code_samples/action_basics/README.md +++ b/code_samples/action_basics/README.md @@ -13,7 +13,7 @@ This Plugin registers the [`PopupDialogAction`][file:PopupDialogAction] action, Additional features of the plugin: - [Using the ``][docs:action-override] element in an `` 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 `` 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 `` is demonstrated in the declaration to add a new group to the `EditorPopupMenu`. ### Actions diff --git a/code_samples/comparing_references_inspection/settings.gradle b/code_samples/comparing_references_inspection/settings.gradle index 85de655af..92a604d5b 100644 --- a/code_samples/comparing_references_inspection/settings.gradle +++ b/code_samples/comparing_references_inspection/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'comparing_references_inspection' - diff --git a/code_samples/conditional_operator_intention/settings.gradle b/code_samples/conditional_operator_intention/settings.gradle index c50116dff..2b0c087b3 100644 --- a/code_samples/conditional_operator_intention/settings.gradle +++ b/code_samples/conditional_operator_intention/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'conditional_operator_intention' - diff --git a/code_samples/editor_basics/settings.gradle b/code_samples/editor_basics/settings.gradle index f299fe2ef..07d55a5c0 100644 --- a/code_samples/editor_basics/settings.gradle +++ b/code_samples/editor_basics/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'editor' - diff --git a/code_samples/facet_basics/build.gradle b/code_samples/facet_basics/build.gradle index ccf24e92e..861d18ad8 100644 --- a/code_samples/facet_basics/build.gradle +++ b/code_samples/facet_basics/build.gradle @@ -28,4 +28,3 @@ patchPluginXml { sinceBuild = '202' untilBuild = '202.*' } - diff --git a/code_samples/facet_basics/settings.gradle b/code_samples/facet_basics/settings.gradle index c78e4677d..779d6e8fc 100644 --- a/code_samples/facet_basics/settings.gradle +++ b/code_samples/facet_basics/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'facet' - diff --git a/code_samples/framework_basics/settings.gradle b/code_samples/framework_basics/settings.gradle index 2d5e13bc3..a9f92338b 100644 --- a/code_samples/framework_basics/settings.gradle +++ b/code_samples/framework_basics/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'framework' - diff --git a/code_samples/inspection_basics/settings.gradle b/code_samples/inspection_basics/settings.gradle index e414327fc..338e03801 100644 --- a/code_samples/inspection_basics/settings.gradle +++ b/code_samples/inspection_basics/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'inspection' - diff --git a/code_samples/kotlin_demo/gradle.properties b/code_samples/kotlin_demo/gradle.properties index 4548116e4..7266fc20a 100644 --- a/code_samples/kotlin_demo/gradle.properties +++ b/code_samples/kotlin_demo/gradle.properties @@ -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. -kotlin.code.style=official \ No newline at end of file +kotlin.code.style=official diff --git a/code_samples/kotlin_demo/settings.gradle b/code_samples/kotlin_demo/settings.gradle index 9c9af454d..1c8c3819a 100644 --- a/code_samples/kotlin_demo/settings.gradle +++ b/code_samples/kotlin_demo/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'kotlin' - diff --git a/code_samples/live_templates/build.gradle b/code_samples/live_templates/build.gradle index ec7728c5d..861d18ad8 100644 --- a/code_samples/live_templates/build.gradle +++ b/code_samples/live_templates/build.gradle @@ -27,4 +27,4 @@ patchPluginXml { version = project.version sinceBuild = '202' untilBuild = '202.*' -} \ No newline at end of file +} diff --git a/code_samples/live_templates/settings.gradle b/code_samples/live_templates/settings.gradle index 616325a23..147c11bfc 100644 --- a/code_samples/live_templates/settings.gradle +++ b/code_samples/live_templates/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'live_templates' - diff --git a/code_samples/max_opened_projects/settings.gradle b/code_samples/max_opened_projects/settings.gradle index 60d0c29b4..55cbacdc2 100644 --- a/code_samples/max_opened_projects/settings.gradle +++ b/code_samples/max_opened_projects/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'maxOpenProjects' - diff --git a/code_samples/module/settings.gradle b/code_samples/module/settings.gradle index 58ad5e6e4..d62bfd000 100644 --- a/code_samples/module/settings.gradle +++ b/code_samples/module/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'module' - diff --git a/code_samples/product_specific/README.md b/code_samples/product_specific/README.md index d6099e0ae..ad06b89f3 100644 --- a/code_samples/product_specific/README.md +++ b/code_samples/product_specific/README.md @@ -1,3 +1,3 @@ ## 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. \ No newline at end of file +Please note, all samples in this folder must be imported into Gradle explicitly as they're not included in the default Gradle composite build. diff --git a/code_samples/product_specific/pycharm_basics/settings.gradle b/code_samples/product_specific/pycharm_basics/settings.gradle index 8ebee0383..9c6861831 100644 --- a/code_samples/product_specific/pycharm_basics/settings.gradle +++ b/code_samples/product_specific/pycharm_basics/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'pycharm' - diff --git a/code_samples/project_model/README.md b/code_samples/project_model/README.md index 0cc868dcd..fe395e2df 100644 --- a/code_samples/project_model/README.md +++ b/code_samples/project_model/README.md @@ -3,7 +3,8 @@ ## Quickstart -Project Model Sample project provides five actions that present data extracted using `ProjectRootManager` instance in the message dialogs. Within the implemented actions, you will be able to: +Project Model Sample project provides five actions that present data extracted using `ProjectRootManager` instance in the message dialogs. +Within the implemented actions, you will be able to: - fetch libraries used in the project, - retrieve the information about the module details, - rename the used SDK, diff --git a/code_samples/project_model/settings.gradle b/code_samples/project_model/settings.gradle index 86a5442ae..5854737eb 100644 --- a/code_samples/project_model/settings.gradle +++ b/code_samples/project_model/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'project_model' - diff --git a/code_samples/project_view_pane/build.gradle b/code_samples/project_view_pane/build.gradle index 87766b1eb..2be633770 100644 --- a/code_samples/project_view_pane/build.gradle +++ b/code_samples/project_view_pane/build.gradle @@ -27,4 +27,4 @@ patchPluginXml { version = project.version sinceBuild = '202' untilBuild = '202.*' -} \ No newline at end of file +} diff --git a/code_samples/project_view_pane/settings.gradle b/code_samples/project_view_pane/settings.gradle index 648d283b5..cb21b2daf 100644 --- a/code_samples/project_view_pane/settings.gradle +++ b/code_samples/project_view_pane/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'project_view_pane' - diff --git a/code_samples/project_wizard/build.gradle b/code_samples/project_wizard/build.gradle index 87766b1eb..2be633770 100644 --- a/code_samples/project_wizard/build.gradle +++ b/code_samples/project_wizard/build.gradle @@ -27,4 +27,4 @@ patchPluginXml { version = project.version sinceBuild = '202' untilBuild = '202.*' -} \ No newline at end of file +} diff --git a/code_samples/project_wizard/settings.gradle b/code_samples/project_wizard/settings.gradle index 9c97cc1ae..d74cb9bfa 100644 --- a/code_samples/project_wizard/settings.gradle +++ b/code_samples/project_wizard/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'projectWizard' - diff --git a/code_samples/run_configuration/src/main/java/org/jetbrains/sdk/runConfiguration/DemoSettingsEditor.java b/code_samples/run_configuration/src/main/java/org/jetbrains/sdk/runConfiguration/DemoSettingsEditor.java index 6c61b0ebe..247be2aef 100644 --- a/code_samples/run_configuration/src/main/java/org/jetbrains/sdk/runConfiguration/DemoSettingsEditor.java +++ b/code_samples/run_configuration/src/main/java/org/jetbrains/sdk/runConfiguration/DemoSettingsEditor.java @@ -34,4 +34,3 @@ public class DemoSettingsEditor extends SettingsEditor { myScriptName.setComponent(new TextFieldWithBrowseButton()); } } - diff --git a/code_samples/settings/settings.gradle b/code_samples/settings/settings.gradle index 4be28a012..bd70031ec 100644 --- a/code_samples/settings/settings.gradle +++ b/code_samples/settings/settings.gradle @@ -1,2 +1 @@ rootProject.name = 'settings' - diff --git a/code_samples/simple_language_plugin/settings.gradle b/code_samples/simple_language_plugin/settings.gradle index 87215c406..ec43b68df 100644 --- a/code_samples/simple_language_plugin/settings.gradle +++ b/code_samples/simple_language_plugin/settings.gradle @@ -1,4 +1,3 @@ // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. rootProject.name = 'simple_language_plugin' - diff --git a/code_samples/theme_basics/resources/Lightning.xml b/code_samples/theme_basics/resources/Lightning.xml index 124c83443..4d73a6eef 100644 --- a/code_samples/theme_basics/resources/Lightning.xml +++ b/code_samples/theme_basics/resources/Lightning.xml @@ -196,4 +196,4 @@ - \ No newline at end of file + diff --git a/intro/about.md b/intro/about.md index 605eb8252..3662884c6 100644 --- a/intro/about.md +++ b/intro/about.md @@ -3,19 +3,27 @@ title: About This Guide --- -This guide is split into several parts, similar to a textbook. Each one builds on the content of the previous section, but it is not necessary to read the guide in order. The [Key Topics](key_topics.md) page aims to link to the pages that are necessary to be able to understand the architecture and get started building plugins. +This guide is split into several parts, similar to a textbook. +Each one builds on the content of the previous section, but it is not necessary to read the guide in order. +The [Key Topics](key_topics.md) page aims to link to the pages that are necessary to be able to understand the architecture and get started building plugins. -> **NOTE** While browsing this guide, you will notice that there are topics that are greyed out. Unfortunately, the guide is not complete and contains placeholders for specific topics. We are working on increasing the coverage, but if you get stuck due to missing content, please see the [Getting Help](getting_help.md) section for details on how to get moving again. +> **NOTE** While browsing this guide, you will notice that there are topics that are greyed out. +> Unfortunately, the guide is not complete and contains placeholders for specific topics. +> We are working on increasing the coverage, but if you get stuck due to missing content, please see the [Getting Help](getting_help.md) section for details on how to get moving again. > -> The guide is also [Open Source on GitHub](https://github.com/JetBrains/intellij-sdk-docs), and Pull Requests for new content or updates are always gratefully received. A Pull Request does not need to be fully comprehensive - if a little update would help you, it will help other developers too! All pull requests will be reviewed before being accepted, so don't worry about inaccuracies. Please see the [Contributing](/CONTRIBUTING.md) page for details on building the guide locally and contributing. +> The guide is also [Open Source on GitHub](https://github.com/JetBrains/intellij-sdk-docs), and Pull Requests for new content or updates are always gratefully received. +> A Pull Request does not need to be fully comprehensive - if a little update would help you, it will help other developers too! All pull requests will be reviewed before being accepted, so don't worry about inaccuracies. +> Please see the [Contributing](/CONTRIBUTING.md) page for details on building the guide locally and contributing. #### [Part I - Plugins](/basics/basics.md) -Describes how to create a plugin that can extend the _IntelliJ Platform_. Includes details on how to set up the project, register extension points, target specific versions of the _IntelliJ Platform_, and how to package, deploy, and test your plugins. +Describes how to create a plugin that can extend the _IntelliJ Platform_. +Includes details on how to set up the project, register extension points, target specific versions of the _IntelliJ Platform_, and how to package, deploy, and test your plugins. #### [Part II - Base Platform](/platform/fundamentals.md) -Describes the foundational layer of the architecture, which provides many features and utilities, such as the component model, the user interface, documents and editors, the virtual file system, settings, threading, and background tasks. The Base Platform layer mainly comprises the functionality of the _IntelliJ Platform_ that does not target language features or parsing. +Describes the foundational layer of the architecture, which provides many features and utilities, such as the component model, the user interface, documents and editors, the virtual file system, settings, threading, and background tasks. +The Base Platform layer mainly comprises the functionality of the _IntelliJ Platform_ that does not target language features or parsing. #### [Part III - Project Model](/basics/project_structure.md) @@ -23,11 +31,14 @@ Documents the Project Model, which represents the files and configuration of the #### [Part IV - PSI](/basics/architectural_overview/psi.md) -The Program Structure Interface builds the syntactic and semantic models for lots of different file types. This section describes how to work with the PSI, navigating and manipulating the syntax trees, and also looks at the powerful references system, which allows a syntax tree node to reference an item in the semantic model. It also details how PSI creates and uses indexes. +The Program Structure Interface builds the syntactic and semantic models for lots of different file types. +This section describes how to work with the PSI, navigating and manipulating the syntax trees, and also looks at the powerful references system, which allows a syntax tree node to reference an item in the semantic model. +It also details how PSI creates and uses indexes. #### Part V - Features -Describes how to extend and interact with various features that use the PSI layer, such as code completion, navigation, Alt+Enter 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, Alt+Enter items, intentions, refactorings, and more. +See also the section on Custom Languages below for language-specific features that are only applicable when adding support for a new language. #### [Part VI - Testing](/basics/testing_plugins/testing_plugins.md) @@ -35,11 +46,14 @@ Describes the available infrastructure for writing automated tests covering the #### [Part VII - Custom Languages](/reference_guide/custom_language_support.md) -Plugins frequently extend support for existing languages, such as adding inspections to Java files. This section describes how to add support to the _IntelliJ Platform_ for a new language that isn't supported by default, creating parsers, syntactic and semantic models, and all the features that build on top. +Plugins frequently extend support for existing languages, such as adding inspections to Java files. +This section describes how to add support to the _IntelliJ Platform_ for a new language that isn't supported by default, creating parsers, syntactic and semantic models, and all the features that build on top. #### [Part VIII - Product Specific](/products/dev_alternate_products.md) -A lot of the functionality in the _IntelliJ Platform_ is language and product agnostic. For example, code inspections work the same in Java as they do in Ruby; it is just the syntax trees and semantic information that is different. This section describes product-specific features, such as specific project model differences and how to target them in a plugin. +A lot of the functionality in the _IntelliJ Platform_ is language and product agnostic. +For example, code inspections work the same in Java as they do in Ruby; it is just the syntax trees and semantic information that is different. +This section describes product-specific features, such as specific project model differences and how to target them in a plugin. #### Part IX - Custom IDEs diff --git a/intro/getting_help.md b/intro/getting_help.md index b7165791e..1a17a7501 100644 --- a/intro/getting_help.md +++ b/intro/getting_help.md @@ -5,7 +5,8 @@ title: Getting Help ## 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. @@ -15,7 +16,8 @@ If you just want to share feedback on the guide, again, [raise an issue](https:/ For problems related to code, rather than the content of the guide, you have several options: -* [Plugin Development Forum](https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development) - post a message to the support forum. It is regularly updated with answers by JetBrains team members. +* [Plugin Development Forum](https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development) - post a message to the support forum. + It is regularly updated with answers by JetBrains team members. * [#intellij-platform on JetBrains Platform Slack](https://plugins.jetbrains.com/slack/) - this chat room is a great place to ask questions, with answers coming from both JetBrains team members and members of the community Of course, all issues will be used to try and improve this guide. diff --git a/intro/intellij_platform.md b/intro/intellij_platform.md index d854b705c..b9e4f48f5 100644 --- a/intro/intellij_platform.md +++ b/intro/intellij_platform.md @@ -3,44 +3,60 @@ title: What is the IntelliJ Platform? --- -The _IntelliJ Platform_ is not a product in and of itself but provides a platform for building IDEs. It is used to power JetBrains products such as [IntelliJ IDEA](https://www.jetbrains.com/idea/). It is also Open Source and can be used by third parties to build IDEs, such as [Android Studio](https://developer.android.com/studio/index.html) from Google. +The _IntelliJ Platform_ is not a product in and of itself but provides a platform for building IDEs. +It is used to power JetBrains products such as [IntelliJ IDEA](https://www.jetbrains.com/idea/). +It is also Open Source and can be used by third parties to build IDEs, such as [Android Studio](https://developer.android.com/studio/index.html) from Google. -The IntelliJ Platform provides all of the infrastructures that these IDEs need to provide rich language tooling support. It provides a component-driven, cross-platform JVM based application host with a high-level user interface toolkit for creating tool windows, tree views, and lists (supporting fast search) as well as popup menus and dialogs. +The IntelliJ Platform provides all of the infrastructures that these IDEs need to provide rich language tooling support. +It is a component-driven, cross-platform JVM based application host with a high-level user interface toolkit for creating tool windows, tree views, and lists (supporting fast search) as well as popup menus and dialogs. -It also includes an image editor as well as a full-text editor and provides abstract implementations of syntax highlighting, code folding, code completion, and other rich text editing features. +The IntelliJ Platform has a full-text editor with abstract implementations of syntax highlighting, code folding, code completion, and other rich text editing features. +An image editor is also included. -Furthermore, it includes open APIs to build common IDE functionality, such as a project model and a build system. It also provides an infrastructure for a very rich debugging experience, with language-agnostic advanced breakpoint support, call stacks, watch windows, and expression evaluation. +Furthermore, it includes open APIs to build standard IDE functionality, such as a project model and a build system. +It also provides an infrastructure for a rich debugging experience, with language-agnostic advanced breakpoint support, call stacks, watch windows, and expression evaluation. -But the IntelliJ Platform's real power comes from the Program Structure Interface (PSI). It is a set of functionalities used to parse files and build rich syntactic and semantic models of the code, and to build indexes from this data. PSI powers a lot of functionality, from quick, navigating to files, types, and symbols, to the contents of code completion windows and find usages, code inspections, and code rewriting, for quick fixes or refactorings, as well as many other features. +But the IntelliJ Platform's real power comes from the Program Structure Interface (PSI). +It is a set of functionalities used to parse files, build rich syntactic and semantic models of the code, and build indexes from this data. +PSI powers a lot of functionality, from quick navigating to files, types, and symbols, to the contents of code completion windows and find usages, code inspections, and code rewriting, for quick fixes or refactorings, as well as many other features. The IntelliJ Platform includes parsers and a PSI model for many languages, and its extensible nature means that it is possible to add support for other languages. ## Plugins -Products built on the IntelliJ Platform are extensible applications, with the platform being responsible for the creation of components, and the injection of dependencies into classes. The IntelliJ Platform fully supports plugins, and JetBrains hosts the [JetBrains Plugin Repository](https://plugins.jetbrains.com) that can be used to distribute plugins that support one or more of the products. It is also possible to host your repositories and distribute plugins separately. +Products built on the IntelliJ Platform are extensible applications, with the platform being responsible for creating components and the injection of dependencies into classes. +The IntelliJ Platform fully supports plugins, and JetBrains hosts the [JetBrains Plugin Repository](https://plugins.jetbrains.com) can be used to distribute plugins that support one or more of the products. +It is also possible to host your repositories and distribute plugins separately. -Plugins can extend the platform in lots of ways, from adding a simple menu item to adding support for a complete language, build system, and debugger. A lot of the existing functionality in the IntelliJ Platform is written as plugins that can be included or excluded depending on the needs of the end product. See the [Quick Start Guide](/basics/basics.md) for more details. +Plugins can extend the platform in many ways, from adding a simple menu item to adding support for a complete language, build system, and debugger. +Many of the existing functionality in the IntelliJ Platform is written as plugins that can be included or excluded depending on the needs of the end product. +See the [Quick Start Guide](/basics/basics.md) for more details. -The IntelliJ Platform is a JVM application, written mostly in Java and Kotlin. You should be experienced with these languages, large libraries written in them, their associated tooling, and large open-source projects to write plugins for products based on the IntelliJ Platform. At this time, it's not possible to extend the IntelliJ Platform in non-JVM languages. +The IntelliJ Platform is a JVM application, written mostly in Java and Kotlin. +You should be experienced with these languages, large libraries written in them, their associated tooling, and large open-source projects to write plugins for products based on the IntelliJ Platform. +At this time, it's not possible to extend the IntelliJ Platform in non-JVM languages. ## Open Source -The IntelliJ Platform is Open Source, under the [Apache license](upsource:///LICENSE.txt), and [hosted on GitHub](https://github.com/JetBrains/intellij-community). +The IntelliJ Platform is Open Source, under the [Apache License](upsource:///LICENSE.txt), and [hosted on GitHub](https://github.com/JetBrains/intellij-community). -While this guide refers to the IntelliJ Platform as a separate entity, there is no "IntelliJ Platform" GitHub repository. Instead, the platform is considered to be an almost complete overlap with the IntelliJ IDEA Community Edition, which is a free and Open Source version of IntelliJ IDEA Ultimate (the GitHub repository linked above is the [JetBrains/intellij-community](https://github.com/JetBrains/intellij-community) repository). +While this guide refers to the IntelliJ Platform as a separate entity, there is no "IntelliJ Platform" GitHub repository. +Instead, the platform is considered to be an almost complete overlap with the IntelliJ IDEA Community Edition, which is a free and Open Source version of IntelliJ IDEA Ultimate (the GitHub repository linked above is the [JetBrains/intellij-community](https://github.com/JetBrains/intellij-community) repository). -The version of the IntelliJ Platform is defined by the version of the corresponding release of IntelliJ IDEA Community Edition. -For example, to build a plugin against IntelliJ IDEA (2019.1.1) build #191.6707.61 means specifying the same build number tag to get the correct Intellij Platform files from the `intellij-community` repository. +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. See the [build number ranges](/basics/getting_started/build_number_ranges.md) page for more information about build numbers corresponding to version numbering. -Typically, an IDE that is based on the IntelliJ Platform will include the `intellij-community` repository as a Git submodule and provide configuration to describe which plugins from the `intellij-community`, and which custom plugins will make up the product. This is how the IDEA Ultimate team works, and they contribute code to both the custom plugins and the IntelliJ Platform itself. +Typically, an IDE that is based on the IntelliJ Platform will include the `intellij-community` repository as a Git submodule and provide configuration to describe which plugins from the `intellij-community`, and which custom plugins will make up the product. +This is how the IDEA Ultimate team works, and they contribute code to both the custom plugins and the IntelliJ Platform itself. ### IDEs Based on the IntelliJ Platform -The IntelliJ Platform underlies many JetBrains IDEs. -IntelliJ IDEA Ultimate is a superset of the IntelliJ IDEA Community Edition but includes closed source plugins ([see this feature comparison](https://www.jetbrains.com/idea/features/editions_comparison_matrix.html)). Similarly, other products such as WebStorm and DataGrip are based on the IntelliJ IDEA Community Edition, but with a different set of plugins included and excluding other default plugins. +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. 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. 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/) * [PyCharm](https://www.jetbrains.com/pycharm/) * [Rider](#rider) - * [RubyMine](https://www.jetbrains.com/ruby/) - * [WebStorm](https://www.jetbrains.com/webstorm/) + * [RubyMine](https://www.jetbrains.com/ruby/) + * [WebStorm](https://www.jetbrains.com/webstorm/) * [Android Studio](https://developer.android.com/studio/index.html) IDE from Google. * [Comma](https://commaide.com/) IDE for Raku (formerly known as Perl 6) * [CUBA Studio](https://www.cuba-platform.com/) #### Rider -JetBrains [Rider](https://www.jetbrains.com/rider/) uses the IntelliJ Platform differently than other IntelliJ based IDEs. It uses the IntelliJ Platform to provide the user interface for a C# and .NET IDE, with the standard IntelliJ editors, tool windows, debugging experience, and so on. It also integrates into the standard Find Usages and Search Everywhere UI, and makes use of code completion, syntax highlighting, and so on. +JetBrains [Rider](https://www.jetbrains.com/rider/) uses the IntelliJ Platform differently than other IntelliJ based IDEs. +It uses the IntelliJ Platform to provide the user interface for a C# and .NET IDE, with the standard IntelliJ editors, tool windows, debugging experience, etc. +It also integrates into the standard Find Usages and Search Everywhere UI and uses code completion, syntax highlighting, and so on. -However, Rider doesn't create a full PSI (syntactic and semantic) model for C# files. Instead, it reuses [ReSharper](https://www.jetbrains.com/resharper/) to provide language functionality. All of the C# PSI model, all inspections and code rewriting, such as quick fixes and refactorings are run out of the process, in a command- line version of ReSharper. This means that creating a plugin for Rider involves two parts - a plugin that lives in the IntelliJ "front end" to show user interface, and a plugin that lives in the ReSharper "back end" to analyze and work with the C# PSI. +However, Rider doesn't create a full PSI (syntactic and semantic) model for C# files. +Instead, it reuses [ReSharper](https://www.jetbrains.com/resharper/) to provide language functionality. +All of the C# PSI model, inspections, code rewritings, such as quick fixes and refactorings are run out of the process, in a command-line version of ReSharper. +This means that creating a plugin for Rider involves two parts - a plugin that lives in the IntelliJ "front end" to show user interface, and a plugin that lives in the ReSharper "back end" to analyze and work with the C# PSI. -Fortunately, many plugins can simply work with the ReSharper backend. The Rider takes care of displaying the results of inspections and code completion, and many plugins can be written that don't require an IntelliJ UI component. More details can be found in the *Part VIII - Product Specific* section. +Fortunately, many plugins can simply work with the ReSharper backend. +The Rider takes care of displaying the results of inspections and code completion, and many plugins can be written that don't require an IntelliJ UI component. +More details can be found in the *Part VIII - Product Specific* section. diff --git a/intro/key_topics.md b/intro/key_topics.md index b5883d743..bc0590e57 100644 --- a/intro/key_topics.md +++ b/intro/key_topics.md @@ -3,23 +3,28 @@ title: Key Topics --- -The _IntelliJ Platform_ is extensive and very capable, and its size and scope can initially be very daunting. This page is intended to list the key topics that a plugin author would be interested in, and provide quick links to the most common extension points. +The _IntelliJ Platform_ is extensive and very capable, and its size and scope can initially be very daunting. +This page is intended to list the key topics that a plugin author would be interested in, and provide quick links to the most common extension points. ## Essential Concepts - [Creating Your First Plugin](/basics/getting_started.md). - [Testing plugins](/basics/testing_plugins/testing_plugins.md). -- Component model - the _IntelliJ Platform_ is a component-based application and is responsible for creating components and injecting dependencies. Understanding this is necessary for building plugins. +- Component model - the _IntelliJ Platform_ is a component-based application and is responsible for creating components and injecting dependencies. + Understanding this is necessary for building plugins. - [Extension points](/basics/plugin_structure/plugin_extensions.md) - how to register components with extension points, and how to find out what extension points are available. -- [Virtual files](/basics/architectural_overview/virtual_file.md) - all file access should go through the Virtual File System, which abstracts and caches the file system. It means you can work with files that are on the local file system, in a zip file or are old versions from version control. +- [Virtual files](/basics/architectural_overview/virtual_file.md) - all file access should go through the Virtual File System, which abstracts and caches the file system. + It means you can work with files that are on the local file system, in a zip file or are old versions from version control. ## Code Model -The _IntelliJ Platform_'s code model is called the PSI - the [Program Structure Interface](/basics/architectural_overview/psi.md). The PSI parses code, builds indexes, and creates a semantic model. +The _IntelliJ Platform_'s code model is called the PSI - the [Program Structure Interface](/basics/architectural_overview/psi.md). +The PSI parses code, builds indexes, and creates a semantic model. ## Common Extension Points -The _IntelliJ Platform_ is extremely exceptionally, and most features and services can be extended. Some of the common extension points are: +The _IntelliJ Platform_ is extremely exceptionally, and most features and services can be extended. +Some of the common extension points are: * [Actions](/tutorials/action_system.md) - menu and toolbar items * [Code inspections](/tutorials/code_inspections.md) - code analysis that looks at the syntax trees and semantic models and highlight issues in the editor. diff --git a/intro/sdk_code_guidelines.md b/intro/sdk_code_guidelines.md index 17a9640be..440181437 100644 --- a/intro/sdk_code_guidelines.md +++ b/intro/sdk_code_guidelines.md @@ -9,7 +9,7 @@ For information about contributing to the IntelliJ Platform itself, visit [Contr * Dummy list item {:toc} - + ## Objectives Keep the following considerations in mind while authoring an SDK code sample: * The purpose of an SDK sample is to demonstrate an implementation pattern of the IntelliJ Platform. @@ -17,16 +17,16 @@ Keep the following considerations in mind while authoring an SDK code sample: * Instructional code differs from production code in some key aspects: * Sacrifice some robustness in the interest of simplicity and brevity. Use error checking where it is necessary to make a point about an implementation pitfall. - * Keep implementations as simple as possible, but use the full features of the IntelliJ Platform, programming language, and libraries. + * Keep implementations as simple as possible, but use the full features of the IntelliJ Platform, programming language, and libraries. * Use meaningful names for interfaces, classes, fields, methods, and extension points. - * Write instructional JavaDoc comments. - * Code samples replace lots of documentation. + * Write instructional JavaDoc comments. + * Code samples replace lots of documentation. * Aim for two levels of SDK samples: - * A _basic_ sample is focused on a particular subject by demonstrating a limited area of the IntelliJ Platform. - It should show all the components and architecture but ultimately accomplish something elementary. + * A _basic_ sample is focused on a particular subject by demonstrating a limited area of the IntelliJ Platform. + It should show all the components and architecture but ultimately accomplish something elementary. For example, demonstrate persistence by storing only a `String`. * An _advanced_ sample demonstrates how different parts of the IntelliJ Platform integrate and work together, such as combining inspections or intentions with non-trivial PsiTree manipulation. - + Ultimately, the goal is to provide developers with roadmaps for implementing functionality in an IntelliJ Platform-based plugin. Each roadmap should contain: * Pointers to SDK documentation about the IntelliJ Platform APIs needed to implement the functionality. @@ -36,11 +36,12 @@ Each roadmap should contain: ## Plugin Copyright Statements Use the standard intellij-community copyright notice in all sample plugins authored by JetBrains: -```text -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." +```text +Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file." ``` -> **NOTE** The copyright statement must appear at the top of every source file. Use the [IntelliJ Platform SDK](https://github.com/JetBrains/intellij-sdk-docs/tree/master/.idea/copyright) copyright profile. +> **NOTE** The copyright statement must appear at the top of every source file. +> Use the [IntelliJ Platform SDK](https://github.com/JetBrains/intellij-sdk-docs/tree/master/.idea/copyright) copyright profile. ## Directory Naming Conventions for SDK Plugins For _basic_ samples, the plugin directory name is derived from the IntelliJ Platform extension points demonstrated. @@ -75,13 +76,13 @@ The plugin ID appears between `` elements in the `plugin.xml` file. In general, the plugin ID is the `Group ID` concatenated with the `Artifact ID`. For example, a plugin like `facet_basics` has the plugin ID `org.intellij.sdk.facet`. -Plugin IDs do not contain underscores. +Plugin IDs do not contain underscores. ## Plugin Package Names Packages in plugins should begin with the plugin ID. If there is only one package in a plugin, then the package name is the same as the plugin ID. Additional suffix words, separated by "." characters, can be added to form more specific package names. -Package names do not contain underscores. +Package names do not contain underscores. ## Plugin Directory Structure SDK sample code should have a standard directory footprint. @@ -116,13 +117,13 @@ code_samples/ settings.gradle ``` -## build.gradle Conventions -New SDK code samples should be developed [using Gradle](/tutorials/build_system.md). +## build.gradle Conventions +New SDK code samples should be developed [using Gradle](/tutorials/build_system.md). As of this writing, the use of Gradle in SDK code samples still relies heavily on the `plugin.xml` for specifying the plugin configuration. -At a later, second phase, the SDK code samples will transition to rely more on the Gradle configuration. +At a later, second phase, the SDK code samples will transition to rely more on the Gradle configuration. -The default contents of a `build.gradle` file are produced by the [New Project Wizard](/tutorials/build_system/prerequisites.md#creating-a-gradle-based-intellij-platform-plugin-with-new-project-wizard). -A consistent structure for an SDK code sample's `build.gradle` file is essential for clarity and is based on the default produced by the project wizard. +The default contents of a `build.gradle` file are produced by the [New Project Wizard](/tutorials/build_system/prerequisites.md#creating-a-gradle-based-intellij-platform-plugin-with-new-project-wizard). +A consistent structure for an SDK code sample's `build.gradle` file is essential for clarity and is based on the default produced by the project wizard. Comments in SDK code sample `build.gradle` files should only draw attention to the parts of the Gradle configuration that are unique for a plugin. For SDK code samples, a few alterations are needed to the default `build.gradle` file produced by the plugin wizard: @@ -131,14 +132,14 @@ For SDK code samples, a few alterations are needed to the default `build.gradle` * Add the following statement to the [Setup DSL](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#setup-dsl) (`intellij{}`) section: ```groovy // Prevents patching attributes in plugin.xml - updateSinceUntilBuild = false - ``` + updateSinceUntilBuild = false + ``` * Add the following statement to the [Patching DSL](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#patching-dsl) (`patchPluginXml{}`) section: ```groovy // Patches value in plugin.xml version = project.version - ``` - + ``` + ## plugin.xml Conventions A consistent structure for the [`plugin.xml`](/basics/plugin_structure/plugin_configuration_file.md) configuration file of an SDK code sample is important because we want to draw attention to the unique parts of the file for a plugin. Comment profusely about unique elements and configurations, and comment sparingly for the rest. @@ -150,7 +151,7 @@ The sequence of elements in an SDK code sample `plugin.xml` file is: The name must start with "SDK: ". * `` The code sample's version in MAJOR.MINOR.FIX format. * MAJOR corresponds to a significant upgrade in functionality. - * MINOR corresponds to minor refactoring and small improvements in functionality. + * MINOR corresponds to minor refactoring and small improvements in functionality. * FIX corresponds to changes that fix problems without significant refactoring. * `` Set the attributes: * `since-build` attribute to the earliest compatible build number of the IntelliJ Platform. @@ -159,13 +160,13 @@ The sequence of elements in an SDK code sample `plugin.xml` file is: SDK code samples are reviewed before every major release (20XX.1) to ensure compatibility with the latest IntelliJ Platform. Add this attribute if a plugin sample is deprecated with a release of the IntelliJ Platform. * `` Include at least one dependency with the module `com.intellij.modules.platform` to indicate basic plugin compatibility with IntelliJ Platform-based products. - Add `` elements containing module FQNs as needed to describe more specialized [Compatibility with Multiple Products](/basics/getting_started/plugin_compatibility.md), and any other [Plugin Dependencies](/basics/plugin_structure/plugin_dependencies.md). + Add `` elements containing module FQNs as needed to describe more specialized [Compatibility with Multiple Products](/basics/getting_started/plugin_compatibility.md), and any other [Plugin Dependencies](/basics/plugin_structure/plugin_dependencies.md). * `` is a concise explanation of what is being demonstrated and how a user would access the functionality. If the plugin by default overrides IDE behavior (such as `tree_structure_provider`) it must be noted in the description. * `` is an ordered list by version numbers with a brief description of changes for each version. * `` Set the value to `IntelliJ Platform SDK`. Set the attributes: - * `email` omit this attribute. + * `email` omit this attribute. * `url` to the JetBrains Plugins Repository `"https://plugins.jetbrains.com"` * The remainder of the [plugin configuration elements](/basics/plugin_structure/plugin_configuration_file.md) should only appear a specific plugin needs them. @@ -174,7 +175,7 @@ IntelliJ Platform SDK code samples should be built and tested against the `since Code samples should build cleanly, with no warnings or errors, and new code samples should pass all default IntelliJ IDEA code inspections. -Testers should complete the following checklist. +Testers should complete the following checklist. Here the term "IDE" means the IntelliJ Platform-based IDE in which the plugin is designed to run: * The plugin should load in the IDE. * The correct information about the plugin should display in the **Preferences \| Plugins** panel. diff --git a/intro/sdk_style.md b/intro/sdk_style.md index eb4f8c6c1..91cd4b267 100644 --- a/intro/sdk_style.md +++ b/intro/sdk_style.md @@ -8,7 +8,7 @@ Before you begin, please read this page thoroughly, as well as the [Code of Cond For information about contributing to the IntelliJ Platform itself, please visit [Contributing to the IntelliJ Platform](/basics/platform_contributions.md). First and foremost, we should keep in mind our audience and their objectives: -_Someone reading technical content is usually looking to answer a specific question. +_Someone reading technical content is usually looking to answer a specific question. That question might be broad or narrowly-focused, but either way, our goal is to provide answers without distraction._ The style of the _Intellij Platform SDK_ documentation is captured by using a markup language named [_Markdown_](https://github.github.com/gfm/). @@ -18,19 +18,19 @@ The following sections describe the SDK documentation style in terms of the Mark {:toc} ## Documentation Markup -By default, when building the site, all files are copied to the destination `_site` folder. -Some files are excluded in the `_config.yml` and `sdkdocs-template/jekyll/_config-defaults.yml` files. +By default, when building the site, all files are copied to the destination `_site` folder. +Some files are excluded in the `_config.yml` and `sdkdocs-template/jekyll/_config-defaults.yml` files. The documentation files themselves are [Markdown](https://github.github.com/gfm/) files (`*.md`) that get automatically converted to HTML when the site is built. ### Liquid Tags and Filters -Jekyll uses the [Liquid](https://shopify.github.io/liquid/) templating language to process files. -This process means standard Liquid tags and filters are available. -There should be little need to use them, however, as the Markdown format is already quite rich. +Jekyll uses the [Liquid](https://shopify.github.io/liquid/) templating language to process files. +This process means standard Liquid tags and filters are available. +There should be little need to use them, however, as the Markdown format is already quite rich. See the [Jekyll site](https://jekyllrb.com/docs/liquid/) for more details. ### Page Format -Only Markdown files beginning with a [YAML](https://yaml.org) header are converted to HTML. -If the Markdown file doesn't contain a header, it won't be converted. +Only Markdown files beginning with a [YAML](https://yaml.org) header are converted to HTML. +If the Markdown file doesn't contain a header, it won't be converted. In other words, to convert a `.md` file to HTML, it should look like this: ```yaml @@ -40,14 +40,15 @@ In other words, to convert a `.md` file to HTML, it should look like this: Lorem ipsum... ``` -The two lines at the top of the file are the markers of the YAML _front matter_. -Fields can be added in between these markers, and are used when generating the HTML. +The two lines at the top of the file are the markers of the YAML _front matter_. +Fields can be added in between these markers, and are used when generating the HTML. Typically, this header is empty, although it is required by Jekyll (if omitted, the file isn't converted). -The YAML header can contain data that is used when generating the site. +The YAML header can contain data that is used when generating the site. For example, the page title can be specified as a simple piece of Markdown - `# Title`, or it can be specified in the YAML, and the page template displays it appropriately: -> **NOTE** The page copyright notice should appear immediately below the YAML header, as shown below. Use the [IntelliJ Platform SDK](https://github.com/JetBrains/intellij-sdk-docs/tree/master/.idea/copyright) copyright profile. +> **NOTE** The page copyright notice should appear immediately below the YAML header, as shown below. +> Use the [IntelliJ Platform SDK](https://github.com/JetBrains/intellij-sdk-docs/tree/master/.idea/copyright) copyright profile. ```yaml --- @@ -66,7 +67,7 @@ Line spacing around headings in Markdown files generally doesn't affect the HTML * Two spaces before a heading that is higher-level than the heading of the previous section. ### Redirects -The documentation site is set up to include the [jekyll-redirect-from](https://github.com/jekyll/jekyll-redirect-from) plugin, which generates "dummy" pages that automatically redirect to a given page. +The documentation site is set up to include the [jekyll-redirect-from](https://github.com/jekyll/jekyll-redirect-from) plugin, which generates "dummy" pages that automatically redirect to a given page. For example, to specify that the `index.html` page be generated to redirect to `README.md`, the `README.md` file should include the following in the YAML header: ```yaml @@ -78,10 +79,10 @@ redirect_from: Lorem ipsum... ``` -The redirect will create an `index.html` file that will automatically redirect to the generated `README.html` file. +The redirect will create an `index.html` file that will automatically redirect to the generated `README.html` file. Redirects enable the site URL to show the `README.html` file automatically - `http://localhost:4001/foo-test/` will try to load `index.html`, which will automatically redirect to `README.html`. -It is also useful to redirect when renaming or moving files. +It is also useful to redirect when renaming or moving files. Multiple redirects can be added to the YAML header. > **NOTE** Please update all existing internal links to the new page location. @@ -90,7 +91,7 @@ Multiple redirects can be added to the YAML header. The site is configured to use the [Kramdown Markdown converter](https://kramdown.gettalong.org), which adds some extra features over traditional Markdown. For example, "attribute lists" that can apply attributes to the generated elements. -One useful attribute is `{:toc}`, which can be applied to a list item, which will get replaced with a list of links to header items. +One useful attribute is `{:toc}`, which can be applied to a list item, which will get replaced with a list of links to header items. E.g., the following list item will be replaced by links to all of the header items in the page: ```md @@ -99,7 +100,7 @@ E.g., the following list item will be replaced by links to all of the header ite ``` ## Content Style -Further Kramdown features are described on the [converter page](https://kramdown.gettalong.org/converter/html.html), and attribute lists are described on the [syntax page](https://kramdown.gettalong.org/syntax.html). +Further Kramdown features are described on the [converter page](https://kramdown.gettalong.org/converter/html.html), and attribute lists are described on the [syntax page](https://kramdown.gettalong.org/syntax.html). Note that source code formatting is configured to use [GitHub Flavoured Markdown](https://help.github.com/articles/github-flavored-markdown/) and "code fences", see below. ### Terminology @@ -115,9 +116,9 @@ Consistent terminology helps the reader grasp new concepts more quickly: Consistent text styles are used to standardize references and keywords: * Menu paths are formatted as bold with pipe characters separating each level: \*\*Settings/Preferences \\\| Editor\*\* (**Settings/Preferences \| Editor**) Menu paths to settings always start with "Settings/Preferences" to cover all platforms. -* Non-code keywords and quotations, or the names of non-code files, are formatted as italic style: \_UI Theme\_ (_UI Theme_), \_README.md\_ (_README.md_.) - Examples of this file type include _LICENSE.txt_ and _README.md_. -* Code keywords, or the names of files containing source code, are formatted as code style: \`interface\` (`interface`), \`plugin.xml\` (`plugin.xml`), \`AnAction\` (`AnAction`) +* Non-code keywords and quotations, or the names of non-code files, are formatted as italic style: \_UI Theme\_ (_UI Theme_), \_README.md\_ (_README.md_.) + Examples of this file type include _LICENSE.txt_ and _README.md_. +* Code keywords, or the names of files containing source code, are formatted as code style: \`interface\` (`interface`), \`plugin.xml\` (`plugin.xml`), \`AnAction\` (`AnAction`) Examples of this file type include `build.gradle`, `AnAction.java` or `theme_basics.theme.json`. * File formats are shown as all capital letters: PNG and XML. * Filename extensions are not capitalized when part of a full filename, path, or URL: `filename.ext`. @@ -126,43 +127,43 @@ Consistent text styles are used to standardize references and keywords: * See [Links to IntelliJ Platform Source](#links-to-intellij-platform-source) for more details about representing names of source files in links. ### Links -Links are handled as standard Markdown links and can be anchored to external sites, pages within the sites, or headings in the sites. +Links are handled as standard Markdown links and can be anchored to external sites, pages within the sites, or headings in the sites. When a Markdown header is converted to an HTML header, it is assigned an ID so that it can be linked. -For example, `## Introduction` gets the ID of `introduction`, and can be linked either in the same page or cross-page as described below. +For example, `## Introduction` gets the ID of `introduction`, and can be linked either in the same page or cross-page as described below. #### General Links General Markdown links have the default Markdown link style: * `[Gradle](https://gradle.org)` ([Gradle](https://gradle.org)) links to an external site, such as companies, articles, etc. * Linking to pages within the SDK documentation: - * `[SDK doc page in current directory](Page2.md)` links to an SDK doc page in the same directory as the current page. + * `[SDK doc page in current directory](Page2.md)` links to an SDK doc page in the same directory as the current page. Note that the extension is `.md`, _NOT_ `.html`. - * `[SDK page in another folder](/Folder2/Page2.md)` links to a page in another folder. + * `[SDK page in another folder](/Folder2/Page2.md)` links to a page in another folder. Note the URL is navigating from the project root. -This format works even if the site is hosted in a sub-folder. +This format works even if the site is hosted in a sub-folder. Relative links also work (`../Folder2/Page2.md`). * Linking to specific _sections_ on pages in the SDK documentation. The anchor name will be all lower case, and spaces are replaced with `-`, e.g. `## Page setup` becomes `#page-setup`. - Once the anchor (`#`) character of the link is entered, the IDE code completion feature shows the available sections. + Once the anchor (`#`) character of the link is entered, the IDE code completion feature shows the available sections. * `[Link to a section on the current page](#another-section)` links to a heading on the current page. - * `[Link to the section on another page](Page2.md#another-section)` links to a heading on another page. + * `[Link to the section on another page](Page2.md#another-section)` links to a heading on another page. #### Links to IntelliJ Platform Source Links to files in the IntelliJ Platform (`intellij-community`) repository use `upsource:///` instead of the full URL to the repository. The `upsource:///` URI effectively points to the root of the `intellij-community` repository. * `[_README.md_](upsource:///README.md)` links to general, non-code information files, use _italic_ style. ([_README.md_](upsource:///README.md)) - Examples of this file type include _LICENSE.txt_ and _README.md_. + Examples of this file type include _LICENSE.txt_ and _README.md_. * `[`\`plugin.xml\``](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)` links to declarative source code files, use `code` style. ([`plugin.xml`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)) Examples of this file type include: `settings.gradle`, `plugin.xml` or `theme_basics.theme.json`. * `[`\`AnAction\``](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java)` links to source files for code objects like interfaces and classes, use `code` style but without the file extension. [`AnAction`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java) - Examples of this file type include Java and Kotlin. - * Note the use of \`\` characters surrounding the class name in the link. + Examples of this file type includeJava and Kotlin. + * Note the use of \`\` characters surrounding the class name in the link. * When linking to an API in this manner, the FQN isn't necessary in the link. * No file extension (*.java, *.kt, *.py, etc.) is used by convention. * Be judicious when using such links. - Generally, only one link is needed for a given file on a documentation page. + Generally, only one link is needed for a given file on a documentation page. * Links to files in source code packages in other repositories follow much the same rules, except the links use `https:` instead of `upsource:///`. -### Guidelines for Highlighting Syntax +### Guidelines for Highlighting Syntax In-paragraph code fragments and IntelliJ Platform APIs are formatted according to these rules: * Avoid using qualifiers like "`Foo` interface" or "`Foo` abstract class". Just refer to `Foo`. @@ -176,12 +177,13 @@ In-paragraph code fragments and IntelliJ Platform APIs are formatted according t Exception: the FQN is not used when an extension point is introduced in an upsource [link](#links). * For XML elements, use the tag notation with syntax highlighting: ``. Attributes are shown with syntax highlighting, and attribute values are shown in quotes: `since-build="191"` -* Method names always use empty parentheses: "call `bar()` to apply." +* Method names always use empty parentheses: "call `bar()` to apply." Method names are prefixed with the class/interface name when needed for clarity: `Foo.bar()`. ### Source Code Source code is represented by using [GitHub Flavoured Markdown](https://help.github.com/articles/github-flavored-markdown/) code fences, which are three backticks. -Syntax highlighting is applied by specifying the language after the first set of ticks: + + Syntax highlighting is applied by specifying the language after the first set of ticks: ```csharp // Some C# code @@ -189,22 +191,22 @@ Syntax highlighting is applied by specifying the language after the first set of ```java // Some Java code - ``` + ``` -Here is the list of [supported languages](https://github.com/jneen/rouge/wiki/List-of-supported-languages-and-lexers), and also [Kotlin](https://kotlinlang.org), of course. +Here is the list of [supported languages](https://github.com/jneen/rouge/wiki/List-of-supported-languages-and-lexers), and also [Kotlin](https://kotlinlang.org), of course. > **NOTE** Source code blocks must have one blank line before and after them, and must have a language specification for highlighting. Whole files can be imported on a page using an include statement within code fences. Search the documentation for `% include` to get the correct include statement syntax. - ```java - // Include statement - ``` + ```java + // Include statement + ``` The advantage is the code can come from the `code_samples` directory, so it will be live code that isn't silently stale. -The disadvantage is the file may contain a large class, too large for the documentation page to be useful. -In any case, please keep code samples concise and avoid any unnecessary "surrounding" code or import statements. +The disadvantage is the file may contain a large class, too large for the documentation page to be useful. +In any case, please keep code samples concise and avoid any unnecessary "surrounding" code or import statements. ### Tables -The Kramdown parser also supports tables. +The Kramdown parser also supports tables. The syntax is to use the pipe (`|`) and minus symbols: ```md @@ -231,26 +233,26 @@ The syntax is to use the pipe (`|`) and minus symbols: ### Notes and Callouts -Notes and callouts can be specified using the blockquote syntax. -The converter looks at the first following word to see if it is bold. -If so, it applies a callout style. +Notes and callouts can be specified using the blockquote syntax. +The converter looks at the first following word to see if it is bold. +If so, it applies a callout style. The example below will be displayed as a callout, styled as a "note": > **NOTE** This is a note > **NOTE** This is a note - + The styles available for callouts are: * TODO - Do not use it in the SDK documentation. - Instead, temporarily embed `[//]: # (TODO: description)` comments. + Instead, temporarily embed `[//]: # (TODO: description)` comments. This format isn't visible in the HTML but is recognized by IDE inspections. * TIP - Information that makes the reader more productive. * NOTE - Information that is important for the reader to understand. This callout is reserved for essential points and concepts. * WARNING - Information that is critical for the user to understand to prevent failures or errors. -> **TIP** TODO/todo comments are discouraged in the master branch of `intellij-sdk-docs`. +> **TIP** TODO/todo comments are discouraged in the master branch of `intellij-sdk-docs`. > There are always exceptions, but the best practice is to resolve all TODOs before the final review. > If immediate resolution isn't possible, write a YouTrack [SDK Issue](https://youtrack.jetbrains.com/issues/IJSDK) that captures the TODO and remove the comment from the document. @@ -265,7 +267,7 @@ A resolution of 72 DPI is acceptable but may look blurry on high-resolution moni It is crucial to reduce the size of image files to prevent bloating the repository and impacting the performance of the documentation site. Resize an image to be nearly the desired width on a documentation page. -Reducing an image's dimensions is the most effective way to reduce image file size. +Reducing an image's dimensions is the most effective way to reduce image file size. Also, optimize the image files using a tool such as the [PNG optimizer](https://plugins.jetbrains.com/plugin/7942-png-optimizer). Images are embedded in a document by adding a Markdown link to the image like so: @@ -282,8 +284,8 @@ If the width of an image needs to be adjusted, use Kramdown markup: ## _SUMMARY Site Table of Contents -The table of contents for the site is displayed in the tree view on the left-hand side of the site, and it is generated from the `_SUMMARY.md` file. -It is a simple Markdown list, with each item in the list being a link to another Markdown page, either in the root folder or sub-folders. +The table of contents for the site is displayed in the tree view on the left-hand side of the site, and it is generated from the `_SUMMARY.md` file. +It is a simple Markdown list, with each item in the list being a link to another Markdown page, either in the root folder or sub-folders. The list can have nested items, which are displayed as child items in the table of contents. > ***WARNING*** Every Markdown (`*.md`) document within the SDK repository (`intellij-sdk-docs`) must have an entry in `_SUMMARY.md`. @@ -310,6 +312,6 @@ The contents can be split into "parts" by separating the list into several lists * ... ``` -If a node doesn't have a link but is just plain text, it will still appear in the table of contents but will be greyed out and not clickable. -It acts as a placeholder for a documentation item. +If a node doesn't have a link but is just plain text, it will still appear in the table of contents but will be greyed out and not clickable. +It acts as a placeholder for a documentation item. A placeholder is useful to keep track of what should be documented, but hasn't yet, and can be helpful to show readers that the topic exists, but isn't yet documented (Pull Requests always welcome!). diff --git a/intro/welcome.md b/intro/welcome.md index 21a8416df..2d93d3ef7 100644 --- a/intro/welcome.md +++ b/intro/welcome.md @@ -10,7 +10,7 @@ redirect_from: [![Twitter Follow](https://img.shields.io/twitter/follow/JBPlatform?style=flat-square)](https://twitter.com/JBPlatform/) [![Slack](https://img.shields.io/badge/Slack-%23intellij--platform-blue)](https://plugins.jetbrains.com/slack) -Welcome to the _IntelliJ Platform_ SDK - the primary source of documentation for extending the _IntelliJ Platform_ by creating plugins, custom language support or building a custom IDE. +Welcome to the _IntelliJ Platform_ SDK - the primary source of documentation for extending the _IntelliJ Platform_ by creating plugins, custom language support, or building a custom IDE. ## Getting Started @@ -24,17 +24,20 @@ Welcome to the _IntelliJ Platform_ SDK - the primary source of documentation for ## Updates -See [Content Updates](content_updates.md) for the latest changes. Follow [JBPlatform](https://twitter.com/JBPlatform/) on Twitter and visit [JetBrains Platform Blog](https://blog.jetbrains.com/platform/) for the latest announcements. +See [Content Updates](content_updates.md) for the latest changes. +Follow [JBPlatform](https://twitter.com/JBPlatform/) on Twitter and visit [JetBrains Platform Blog](https://blog.jetbrains.com/platform/) for the latest announcements. Are you upgrading your plugin to the latest platform release? Make sure to check [Incompatible Changes](/reference_guide/api_changes_list.md) as well as [Notable Changes and Features](/reference_guide/api_notable/api_notable.md). -[Dynamic Plugins](/basics/plugin_structure/dynamic_plugins.md) are available in 2020.1. We've also published our roadmap for the IntelliJ Platform for 2020: [Part I](https://blog.jetbrains.com/idea/2019/12/intellij-platform-roadmap-for-2020/) [Part II](https://blog.jetbrains.com/idea/2020/01/intellij-based-ide-features-roadmap-for-2020/) +[Dynamic Plugins](/basics/plugin_structure/dynamic_plugins.md) are available in 2020.1. +We've also published our roadmap for the IntelliJ Platform for 2020: [Part I](https://blog.jetbrains.com/idea/2019/12/intellij-platform-roadmap-for-2020/) [Part II](https://blog.jetbrains.com/idea/2020/01/intellij-based-ide-features-roadmap-for-2020/) > **NOTE** If your plugin depends on Java functionality and targets 2019.2 or later, please make sure to follow the steps from this [blog post](https://blog.jetbrains.com/platform/2019/06/java-functionality-extracted-as-a-plugin/). ## Open Source -This guide is Open Source and licensed under Apache 2.0. The source (as Markdown) is [hosted on GitHub](https://github.com/JetBrains/intellij-sdk-docs). -Please see [CONTRIBUTING.md](/CONTRIBUTING.md) for details on how to host the docs locally and contribute. +This guide is Open Source and licensed under Apache 2.0. +The source (as Markdown) is [hosted on GitHub](https://github.com/JetBrains/intellij-sdk-docs). +Please see [CONTRIBUTING.md](/CONTRIBUTING.md) for details on hosting the docs locally and contributing. -Please see [Getting Help](getting_help.md) if you encounter bugs in this guide or require help with missing content. +Please see [Getting Help](getting_help.md) if you encounter bugs in this guide or require help with missing content. diff --git a/platform/fundamentals.md b/platform/fundamentals.md index 56bb6a56a..36bf3b98d 100644 --- a/platform/fundamentals.md +++ b/platform/fundamentals.md @@ -6,7 +6,7 @@ redirect_from: --- -This section describes the low level fundamental building blocks of the _IntelliJ Platform_: +This section describes the low-level fundamental building blocks of the _IntelliJ Platform_: * The component model - how the application is hosted and composed. Lifetime and dependency management. * [Disposers](/basics/disposers.md) - managing object lifetimes and resource cleanup diff --git a/products/android_studio.md b/products/android_studio.md index b30ac03f2..8c21964d9 100644 --- a/products/android_studio.md +++ b/products/android_studio.md @@ -3,19 +3,19 @@ title: Android Studio Plugin Development --- -## Introduction +## Introduction Android Studio plugins extend or add functionality to the [Android Studio IDE](https://developer.android.com/studio). Plugins can be written in Kotlin or Java, or a mix of both, and are created using IntelliJ IDEA and the [IntelliJ Platform](/intro/intellij_platform.md). It's also helpful to be familiar with [Java Swing](https://docs.oracle.com/javase/8/javase-clienttechnologies.htm). Once completed, plugins can be packaged and distributed at [JetBrains Plugin Repository](https://plugins.jetbrains.com). -Android Studio plugins are not Android modules or apps to run in the Android operating system, such as on a smartphone or tablet. +Android Studio plugins are not Android modules or apps to run in the Android operating system, such as smartphones or tablets. ## Configuring IntelliJ Platform Projects for Android Studio Plugin Development To create a new Android Studio plugin project, follow the tutorial on the [Getting Started with Gradle](/tutorials/build_system/prerequisites.md) page. The tutorial produces a skeleton project suitable to use as a starting point for an Android Studio plugin. On the [New Project Configuration Screen](/tutorials/build_system/prerequisites.md#new-project-configuration-screen) of the New Project Wizard tutorial, choose Gradle from the product category pane as described in the tutorial, **not** _Android_. - + Some minor modifications to the skeleton project are needed, as discussed below. ### Matching Versions of the IntelliJ Platform with the Android Studio Version @@ -34,7 +34,7 @@ The use-case of developing for a non-IntelliJ IDEA IDE is reviewed in the [Plugi The particular example in that section discusses configuring a plugin project for PhpStorm, so the details for an Android Studio plugin project are reviewed here. Here are the steps to configure the `build.gradle` file for developing a plugin to target Android Studio: -* The Gradle plugin attributes describing the configuration of the [IntelliJ Platform used to build the plugin project](/tutorials/build_system/gradle_guide.md#configuring-the-gradle-plugin-for-building-intellij-platform-plugin-projects) must be explicitly set. +* The Gradle plugin attributes describing the configuration of the [IntelliJ Platform used to build the plugin project](/tutorials/build_system/gradle_guide.md#configuring-the-gradle-plugin-for-building-intellij-platform-plugin-projects) must be explicitly set. Continuing with the example [above](#matching-versions-of-the-intellij-platform-with-the-android-studio-version), set the `intellij.version` value to `191.8026.42`. Alternatively, specify `intellij.localPath` to refer to a local installation of Android Studio. * Android Studio plugin projects that use APIs from the `android` plugin must declare a dependency on that plugin. @@ -47,12 +47,12 @@ The snippet below is an example of configuring the Setup and Running DSLs in a ` ```groovy intellij { // Define IntelliJ Platform against which to build the plugin project. - version '191.8026.42' // Same IntelliJ IDEA version (2019.1.4) as target 3.5 Android Studio - type 'IC' // Use IntelliJ IDEA CE because it's the basis of the IntelliJ Platform - // Require the Android plugin, Gradle will match the plugin version to intellij.version - plugins 'android' + version '191.8026.42' // Same IntelliJ IDEA version (2019.1.4) as target 3.5 Android Studio + type 'IC' // Use IntelliJ IDEA CE because it's the basis of the IntelliJ Platform + // Require the Android plugin, Gradle will match the plugin version to intellij.version + plugins 'android' } - + runIde { // Absolute path to installed target 3.5 Android Studio to use as IDE Development Instance // The "Contents" directory is macOS specific. @@ -61,7 +61,7 @@ The snippet below is an example of configuring the Setup and Running DSLs in a ` ``` ### Configuring the Plugin plugin.xml File -As discussed in the [Plugin Dependencies](/basics/getting_started/plugin_compatibility.md#declaring-plugin-dependencies) section of this guide, a plugin's dependency on [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality) must be declared in `plugin.xml`. +As discussed in the [Plugin Dependencies](/basics/getting_started/plugin_compatibility.md#declaring-plugin-dependencies) section of this guide, a plugin's dependency on [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality) must be declared in `plugin.xml`. When using Android Studio-specific features (APIs), a dependency on `com.intellij.modules.androidstudio` must be declared as shown in the code snippet below. Otherwise, if only general IntelliJ Platform features (APIs) are used, then a dependency on `com.intellij.modules.platform` must be declared as discussed in [Plugin Compatibility with IntelliJ Platform Products](/basics/getting_started/plugin_compatibility.md). @@ -70,14 +70,14 @@ Otherwise, if only general IntelliJ Platform features (APIs) are used, then a de ``` ## Additional Articles and Resources -* Discussion of extending Android Lint - [How to Register AndroidLintInspectionBase in IntelliJIdea Plugin](https://intellij-support.jetbrains.com/hc/en-us/community/posts/360005018559-How-to-register-AndroidLintInspectionBase-in-IntellijIdea-Plugin) +* Discussion of extending Android Lint - [How to Register AndroidLintInspectionBase in IntelliJIdea Plugin](https://intellij-support.jetbrains.com/hc/en-us/community/posts/360005018559-How-to-register-AndroidLintInspectionBase-in-IntellijIdea-Plugin) * Grzegorz Matyszczak's article [How I Automated Creating Files for a New Screen with My Own Android Studio Plugin](https://proandroiddev.com/how-i-automated-creating-files-for-a-new-screen-with-my-own-android-studio-plugin-5d54b14ba6fa) * Marcos Holgado's article series [Write an Android Studio Plugin (Part 1)](https://proandroiddev.com/write-an-android-studio-plugin-part-1-creating-a-basic-plugin-af956c4f8b50) ## Open Source Plugins for Android Studio -When learning new development configurations, it is helpful to have some representative projects for reference: +When learning new development configurations, it is helpful to have some representative projects for reference: * [ADB Idea](https://github.com/pbreault/adb-idea) plugin for Android Studio and Intellij IDEA that speeds up Android development. -* [Android postfix plugin](https://github.com/takahirom/android-postfix-plugin) for Android Studio. +* [Android postfix plugin](https://github.com/takahirom/android-postfix-plugin) for Android Studio. * [Flutter Plugin](https://github.com/flutter/flutter-intellij). * Bal Sikandar's [list of Android Studio plugins](https://github.com/balsikandar/Android-Studio-Plugins). diff --git a/products/clion.md b/products/clion.md index 652c5bf0b..440f11298 100644 --- a/products/clion.md +++ b/products/clion.md @@ -24,7 +24,7 @@ Click on an entry in the table's *Attribute* column to go to the documentation a | [`runIde.ideDirectory`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#running-dsl) | Not needed; the Development Instance will automatically match intellij.type | The dependency on the CLion APIs must be declared in the `plugin.xml` file. -As described in [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality) table, the `` elements should contain the CLion module, as illustrated in the `plugin.xml` snippet below: +As described in [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality) table, the `` elements should contain the CLion module, as illustrated in the `plugin.xml` snippet below: ```xml @@ -37,5 +37,5 @@ Test your plugin with versions of CLion you intend to support. ## Open Source Plugins for CLion When learning new APIs, it is helpful to have some representative projects for reference: -* [C/C+​+​ Coverage](https://github.com/zero9178/C-Cpp-Coverage-for-CLion) -* [C/C+​+​ Single File Execution](https://github.com/corochann/SingleFileExecutionPlugin) +* [C/C++ Coverage](https://github.com/zero9178/C-Cpp-Coverage-for-CLion) +* [C/C++ Single File Execution](https://github.com/corochann/SingleFileExecutionPlugin) diff --git a/products/data_grip.md b/products/data_grip.md index 888853dfc..94517cc1d 100644 --- a/products/data_grip.md +++ b/products/data_grip.md @@ -29,7 +29,7 @@ To see how these attributes appear in a similar `build.gradle` file for PhpStorm The additional attribute `runIde.jvmArgs` is required for versions of the `gradle-intellij-plugin` 0.4.16 and earlier. This attribute declares that Gradle should use the DataGrip platform to run/debug plugins in a development instance. It is not required for building plugins and manually installing them in DataGrip. -Benign, but redundant attribute if used for later versions of the `gradle-intellj-plugin`. +Benign, but redundant attribute if used for later versions of the `gradle-intellj-plugin`. The dependency on the DataGrip APIs must be declared in the `plugin.xml` file. As described in [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality) table, the `` tags must declare `com.intellij.database`. diff --git a/products/dev_alternate_products.md b/products/dev_alternate_products.md index 4b2f9da30..94cc27a19 100644 --- a/products/dev_alternate_products.md +++ b/products/dev_alternate_products.md @@ -1,14 +1,15 @@ --- -title: Plugins Targeting IntelliJ Platform-Based IDEs +title: Plugins Targeting IntelliJ Platform-Based IDEs --- -## Introduction +## Introduction Plugin projects can target IDEs other than IntelliJ IDEA, as long as the products are based on the [IntelliJ Platform](/intro/intellij_platform.md). -Such plugins are developed much like plugin projects that target IntelliJ IDEA, and can be written in Kotlin or Java, or a mix of both. +Such plugins are developed much like plugin projects that target IntelliJ IDEA. +They can be written in Kotlin or Java, or a mix of both. Once completed, the plugins can be packaged and distributed at [JetBrains Plugin Repository](https://plugins.jetbrains.com). -Project configuration attributes common to projects targeting products other than IntelliJ IDEA are described here. +Project configuration attributes common to projects targeting products other than IntelliJ IDEA are described here. Details particular to an IntelliJ Platform-based product are described on the individual product pages in Part VIII. All of the Gradle configuration attributes described here are discussed in-depth on the [Configuring Gradle for IntelliJ Platform Plugins](/tutorials/build_system/gradle_guide.md) and the `gradle-intellij-plugin` [README](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md) pages. @@ -22,24 +23,23 @@ To create a new Gradle plugin project, follow the tutorial on the [Getting Start The tutorial produces a skeleton Gradle project suitable to use as a starting point. Modifications are needed to the skeleton project's `build.gradle` and `plugin.xml` files, as described below, and on the individual product pages in Part VIII. -The `build.gradle` file is modified to specify the target product, which determines the APIs available during development. +The `build.gradle` file is modified to specify the target product, determining the APIs available during development. The `plugin.xml` file is modified to declare the plugin's dependency on modules or libraries. -## Configuring Build.Gradle to Target Products other than IntelliJ IDEA +## Configuring Build.Gradle to Target Products other than IntelliJ IDEA The best practice is to use the `gradle-intellij-plugin` `intellij.type` [attribute](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) to specify the target product. For example, `PY` for PyCharm professional. Configuration using an `intellij.type` attribute is explained in the [Product-Specific Attribute](#configuring-plugin-projects-using-a-product-specific-attribute) section below. -However, not all products have an `intellij.type` attribute defined by the `gradle-intellij-plugin`. -For example, PhpStorm. -If the target product does not have an `intellij.type` attribute defined, then the best approach is to configure the project by using the [IntelliJ IDEA Attribute](#configuring-buildgradle-using-the-intellij-idea-product-attribute). +However, not all products have an `intellij.type` attribute defined by the `gradle-intellij-plugin`, for example, PhpStorm. +If the target product does not have an `intellij.type` attribute defined, then the best approach is to configure the project using the [IntelliJ IDEA Attribute](#configuring-buildgradle-using-the-intellij-idea-product-attribute). ### Configuring Plugin Projects Using a Product-Specific Attribute If the `gradle-intellij-plugin` supports a target product directly, there will be an `intellij.type` [attribute](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) defined. Specifying the target as a product-specific `intellij.type` attribute has two advantages: * The APIs available to the plugin will be limited to only what is defined in the target product. (Unless additional plugin dependencies are specified.) -* The default [Development Instance](/basics/ide_development_instance.md) for running the plugin will be the target product. +* The default [Development Instance](/basics/ide_development_instance.md) for running the plugin will be the target product. A `build.gradle` snippet setting a plugin project to target PyCharm is shown below. The `gradle-intellij-plugin` will fetch the matching build of PyCharm Professional to define the APIs available, and use that build of PyCharm (and associated JetBrains runtime) as the Development Instance. @@ -56,7 +56,7 @@ No additional product-specific configuration needs to be set in `build.gradle`: If the `gradle-intellij-plugin` does not directly support an IntelliJ Platform-based product, the `build.gradle` file can still be configured to target the desired product. In this case, the `build.gradle` file is configured to use IntelliJ IDEA (Community or Ultimate Edition) as the basis for the available APIs. This does have the drawback that APIs not specific to the target product might accidentally be included in the plugin project. -However testing the plugin project in the target product helps to find such mistakes. +However, testing the plugin project in the target product helps to find such mistakes. Additional configuration must be done to match the version of IntelliJ IDEA to the version of the target product. Understanding the relationship between build numbers is critical when using this approach to project configuration: @@ -65,7 +65,7 @@ Understanding the relationship between build numbers is critical when using this The IntelliJ Platform is defined by a specific build of the IntelliJ IDEA Community Edition. The Gradle plugin attribute [`intellij.version`](/tutorials/build_system/gradle_guide.md#intellij-platform-configuration) is set to be _baseIntelliJPlatformVersion_. -For API compatibility, the IntelliJ Platform version used in the _targetIDE_ dictates the _baseIntelliJPlatformVersion_ used for developing a plugin. +For API compatibility, the IntelliJ Platform version used in the _targetIDE_ dictates the _baseIntelliJPlatformVersion_ used for developing a plugin. #### Matching Versions of the IntelliJ Platform with the Target IDE Version The _baseIntelliJPlatformVersion_ used in the _targetIDE_ may not be readily apparent, depending on the product. @@ -81,12 +81,12 @@ The version of the IntelliJ Platform used to build this product version is BRANC If the product version isn't clear on the _About_ screen, consult the individual product pages in Part VIII. The [Other IntelliJ IDEA Versions](https://www.jetbrains.com/idea/download/other.html) page is a way to find build numbers for every product version. -Additional ways include hovering over the version number for a product in ToolBox, or examining the _About_ screen for IntelliJ IDEA Community. +Additional ways include hovering over the version number for a product in ToolBox or examining the _About_ screen for IntelliJ IDEA Community. In this example, IntelliJ IDEA Community Edition (which defines the IntelliJ Platform) for 2019.2.4 is build number `192.7142.36`. -Although the FIX versions are different, this is not uncommon between products, and the builds are still compatible. -The BRANCH and BUILD numbers match, therefore in this PhpStorm example: -* The _targetIDE_ is PhpStorm, build `192.7142.41`, -* The _baseIntelliJPlatformVersion_ (IntelliJ IDEA Community Edition) is build `192.7142.36` +Although the FIX versions are different, this is not uncommon between products, and the builds are still compatible. +The BRANCH and BUILD numbers match, therefore in this PhpStorm example: +* The _targetIDE_ is PhpStorm, build `192.7142.41`, +* The _baseIntelliJPlatformVersion_ (IntelliJ IDEA Community Edition) is build `192.7142.36` This information is used to configure the plugin project's `build.gradle` and `plugin.xml` files. @@ -94,7 +94,7 @@ This information is used to configure the plugin project's `build.gradle` and `p Configuring a Gradle plugin project for using _baseIntelliJPlatformVersion_ requires changing some of the default settings in the `build.gradle` file. Changes need to be made in two tasks: `intellij {}` and `runIde {}`. -The Gradle plugin attributes describing the configuration of the [IntelliJ Platform used to build the plugin project](/tutorials/build_system/gradle_guide.md#configuring-the-gradle-plugin-for-building-intellij-platform-plugin-projects) must be explicitly set in the `intellij {}` task. +The Gradle plugin attributes describing the configuration of the [IntelliJ Platform used to build the plugin project](/tutorials/build_system/gradle_guide.md#configuring-the-gradle-plugin-for-building-intellij-platform-plugin-projects) must be explicitly set in the `intellij {}` task. The `intellij.type` is "IU" because although the IntelliJ IDEA Community Edition defines the IntelliJ Platform, the PHP plugin is only compatible with IntelliJ IDEA Ultimate. The `intellij.version` is _baseIntelliJPlatformVersion_. @@ -110,15 +110,15 @@ This snippet is an example for configuring the Setup and Running DSLs in a `buil ```groovy intellij { - // Define IntelliJ Platform against which to build the plugin project. + // Define the IntelliJ Platform against which to build the plugin project. // Use the IntelliJ Platform BRANCH.BUILD version matching "targetIDE" (PhpStorm) - version '192.7142.36' // baseIntelliJPlatformVersion - type 'IU' + version '192.7142.36' // baseIntelliJPlatformVersion + type 'IU' // Require the targetIDE plugin or library - // Use the stable version compatible with intellij.version and intellij.type specified above + // Use the stable version compatible with intellij.version and intellij.type specified above plugins 'com.jetbrains.php:192.6603.42' } - + runIde { // Absolute path to the installed targetIDE to use as IDE Development Instance // Note the Contents directory must be added at the end of the path for macOS. @@ -127,11 +127,12 @@ This snippet is an example for configuring the Setup and Running DSLs in a `buil ``` ## Configuring plugin.xml -As discussed on the [Plugin Dependencies](/basics/getting_started/plugin_compatibility.md#declaring-plugin-dependencies) page of this guide, a plugin's dependency on [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality) must be declared in `plugin.xml`. +As discussed on the [Plugin Dependencies](/basics/getting_started/plugin_compatibility.md#declaring-plugin-dependencies) page of this guide, a plugin's dependency on [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality) must be declared in `plugin.xml`. When using features (APIs) specific to the target product, a dependency on the target product module must be declared, as shown in the code snippet below. Otherwise, if only general IntelliJ Platform features (APIs) are used, then a dependency on `com.intellij.modules.platform` must be declared as discussed in [Plugin Compatibility with IntelliJ Platform Products](/basics/getting_started/plugin_compatibility.md). -> **NOTE** In the special case of a plugin project declaring dependencies only on other plugins, it must also declare a dependency on `com.intellij.modules.platform`. Otherwise, the plugin project is considered to be legacy and will only load in IntelliJ IDEA. +> **NOTE** In the particular case of a plugin project declaring dependencies only on other plugins, it must also declare a dependency on `com.intellij.modules.platform`. +> Otherwise, the plugin project is considered to be legacy and will only load in IntelliJ IDEA. Continuing with the example of developing a plugin for PhpStorm: diff --git a/products/goland.md b/products/goland.md index a34f4acfa..316dbd26c 100644 --- a/products/goland.md +++ b/products/goland.md @@ -16,19 +16,19 @@ The table below summarizes the `gradle-intellij-plugin` attributes to set in the Click on an entry in the table's *Attribute* column to go to the documentation about that attribute. To see how these attributes appear in a similar `build.gradle` file for PhpStorm, see [Configuring build.gradle using the IntelliJ IDEA Product Attribute](/products/dev_alternate_products.md#configuring-buildgradle-using-the-intellij-idea-product-attribute). -| `gradle-intellij-plugin` Attribute | Attribute Value | -|-----------|-------| -| [`intellij.type`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | `IU` for IntelliJ IDEA Ultimate. (The Go plugin isn't compatible with IntelliJ IDEA Community Edition.) | -| [`intellij.version`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | Set to the same `IU` BRANCH.BUILD as the GoLand target version, e.g. `193.5233.102` | -| [`intellij.plugins`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | `org.jetbrains.plugins.go:193.5233.102.83` for the Go plugin.
See below for Go plugin version information. | -| [`runIde.ideDirectory`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#running-dsl) | Path to locally installed target version of GoLand. For example, on macOS:
`/Users//Library/Application Support/JetBrains/Toolbox/apps/Goland/ch-0/193.5233.112/GoLand.app/Contents` | +| `gradle-intellij-plugin` Attribute | Attribute Value | +|------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [`intellij.type`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | `IU` for IntelliJ IDEA Ultimate. (The Go plugin isn't compatible with IntelliJ IDEA Community Edition.) | +| [`intellij.version`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | Set to the same `IU` BRANCH.BUILD as the GoLand target version, e.g. `193.5233.102` | +| [`intellij.plugins`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | `org.jetbrains.plugins.go:193.5233.102.83` for the Go plugin.
See below for Go plugin version information. | +| [`runIde.ideDirectory`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#running-dsl) | Path to locally installed target version of GoLand. For example, on macOS:
`/Users//Library/Application Support/JetBrains/Toolbox/apps/Goland/ch-0/193.5233.112/GoLand.app/Contents` | -The version of the Go plugin is explicitly declared because it isn't bundled with IntelliJ IDEA Ultimate Edition. -Select a [version](https://plugins.jetbrains.com/plugin/9568-go/versions) of the Go plugin that is compatible with the IntelliJ Idea Ultimate version. +The Go plugin version is explicitly declared because it isn't bundled with IntelliJ IDEA Ultimate Edition. +Select a [version](https://plugins.jetbrains.com/plugin/9568-go/versions) of the Go plugin compatible with the IntelliJ Idea Ultimate version. The dependency on the Go plugin APIs must be declared in the `plugin.xml` file. As described in [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality) table, the `` tags must declare `com.intellij.modules.go`. -The `plugin.xml` file must also declare a dependency on `com.intellij.modules.platform` as explained in [Configuring the plugin.xml File](dev_alternate_products.md#configuring-pluginxml). +The `plugin.xml` file must also declare a dependency on `com.intellij.modules.platform` as explained in [Configuring the plugin.xml File](dev_alternate_products.md#configuring-pluginxml). The dependency declaration is illustrated in the `plugin.xml` snippet below: ```xml diff --git a/products/phpstorm/existing_plugins.md b/products/phpstorm/existing_plugins.md index 7a10e9be2..78c3d73ec 100644 --- a/products/phpstorm/existing_plugins.md +++ b/products/phpstorm/existing_plugins.md @@ -1,11 +1,11 @@ --- -title: Example PhpStorm Third Party Plugins +title: Example PhpStorm Third-Party Plugins redirect_from: - /phpstorm/existing_plugins.html --- -This page lists some example PhpStorm plugins created by third party developers. +This page lists some example PhpStorm plugins created by third-party developers. ## Symfony The Symfony plugin is a free plugin for Symfony framework developers. @@ -18,9 +18,10 @@ There are lots of features included into this plugin, such as Symfony-specific c * [Symfony plugin in PhpStorm Plugins Repository](https://plugins.jetbrains.com/plugin/7219-symfony-support) ## Laravel -The Laravel plugin is a free plugin for Laravel developers. +The Laravel plugin is a free plugin for Laravel developers. -It provides code completion and navigation for various Laravel components: controllers, routes, views, configuration, services, and translations. You can also use Laravel-specific live templates for generating various Laravel entities. +It provides code completion and navigation for various Laravel components: controllers, routes, views, configuration, services, and translations. +You can also use Laravel-specific live templates for generating various Laravel entities. * [GitHub](https://github.com/Haehnchen/idea-php-laravel-plugin) * [Laravel Development in PhpStorm](https://www.jetbrains.com/help/phpstorm/laravel.html) @@ -28,7 +29,7 @@ It provides code completion and navigation for various Laravel components: contr ## Laravel Idea The Laravel Idea plugin is a paid plugin for Laravel developers. -It provides a wide array of code generation and code completion features, and includes hundreds of useful helpers, including configuration and translation keys, gates names completion, blade support, and so on. +It provides a wide array of code generation and code completion features and includes hundreds of useful helpers, including configuration and translation keys, gates names completion, blade support, etc. * [Documentation](https://laravel-idea.com/docs/3.x/overview) * [Issue Tracker](https://github.com/laravel-idea/plugin/issues) @@ -36,8 +37,9 @@ It provides a wide array of code generation and code completion features, and in * [Laravel Development in PhpStorm](https://www.jetbrains.com/help/phpstorm/laravel.html) ## Magicento -Magicento is a paid PhpStorm plugin for Magento developers. Free limited version is available. -Features include: Goto for factories and template paths, autocomplete for factories, xml files and class names, documentation for xml nodes, evaluation of PHP code inside Magento environment, and much more to come! +Magicento is a paid PhpStorm plugin for Magento developers. +A free limited version is available. +Features include: Goto for factories and template paths, autocomplete for factories, XML files and class names, documentation for XML nodes, evaluation of PHP code inside the Magento environment, and much more to come! * [Official Magicento Web Site](https://magicento.com/) * [GitHub](https://github.com/enriquepiatti/Magicento) @@ -45,26 +47,28 @@ Features include: Goto for factories and template paths, autocomplete for factor ## YiiStorm YiiStorm is a plugin for PhpStorm IDE that is adding code navigation enhancements for Yii framework based projects. -Features are: Going from render and renderPartial to the view file. Includes controllers, partials and widgets. Supports all ways of specifying a view: themes, smarty .tpl views and external actions; Going from model name in relations() to the model class; Going from the $this->widget('path.to.widget.Class') call to the widget class; Going from controller actions() to action class. +Features are: Going from render and renderPartial to the view file. +Includes controllers, partials, and widgets. +Supports all ways of specifying a view: themes, smarty .tpl views and external actions; Going from model name in relations() to the model class; Going from the $this->widget('path.to.widget.Class') call to the widget class; Going from controller actions() to action class. * [GitHub](https://github.com/cmazx/yiistorm) * [YiiStorm in PhpStorm Plugins Repository](https://plugins.jetbrains.com/plugin/7182-yiistorm) ## Nette -Nette is a family of mature and stand-alone components for PHP they create a framework. +Nette is a family of mature and stand-alone components for PHP that create a framework. * [Official Nette web site](https://nette.org/en/) -| Name | Description | Website | GH | Plugin | -|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|----------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------| -| Nette framework helpers | Nette framework helpers make application development in Nette easier. The plugin provides code completion and navigation for Nette components, annotations, and DI service methods in PHP code. It also implements PHP type by `PhpTypeProvider`. | [Nette web](https://nette.org/en/) | [intellij-nette](https://github.com/nette-intellij/intellij-nette) | [Nette plugin](https://plugins.jetbrains.com/plugin/7231-nette-framework-helpers) | -| Latte | Nette Latte plugin provides support for Latte language – the safest & truly intuitive templates for PHP. The plugin implements custom language. Partially support PHP like in .php files (code completion, inspections, references to classes, methods, properties, etc.). Supports load config from XML files located in the project. It implements Stub indexes and more around custom language. | [Latte web](https://latte.nette.org/en/) | [intellij-latte](https://github.com/nette-intellij/intellij-latte) | [Latte plugin](https://plugins.jetbrains.com/plugin/7457-latte) | -| Neon | Nette Neon is commonly used for any structured data, such as settings, language translations, etc. It is very similar to YAML. The plugin implements custom language. Easy implementation for Go to PHP classes and completion for classes. | [Neon web](https://ne-on.org/) | [intellij-neon](https://github.com/nette-intellij/intellij-neon) | [Neon plugin](https://plugins.jetbrains.com/plugin/7060-neon-support) | -| Nette Tester | Nette Tester is a simple and yet very handy PHP code testing tool. The plugin implements "run configurations" and "run line markers". Supports run configurations in a remote interpreter (eg: in Docker or docker-compose) | [Tester web](https://tester.nette.org/en/) | [intellij-nette-tester](https://github.com/nette-intellij/intellij-nette-tester) | [Tester plugin](https://plugins.jetbrains.com/plugin/8226-nette-tester) | +| Name | Description | Website | GH | Plugin | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|----------------------------------------------------------------------------------|-----------------------------------------------------------------------------------| +| Nette framework helpers | Nette framework helpers make application development in Nette easier. The plugin provides code completion and navigation for Nette components, annotations, and DI service methods in PHP code. It also implements PHP type by `PhpTypeProvider`. | [Nette web](https://nette.org/en/) | [intellij-nette](https://github.com/nette-intellij/intellij-nette) | [Nette plugin](https://plugins.jetbrains.com/plugin/7231-nette-framework-helpers) | +| Latte | Nette Latte plugin supports Latte language – the safest & truly intuitive templates for PHP. The plugin implements custom language. Partially support PHP like in .php files (code completion, inspections, references to classes, methods, properties, etc.). Supports load config from XML files located in the project. It implements Stub indexes and more around custom language. | [Latte web](https://latte.nette.org/en/) | [intellij-latte](https://github.com/nette-intellij/intellij-latte) | [Latte plugin](https://plugins.jetbrains.com/plugin/7457-latte) | +| Neon | Nette Neon is commonly used for any structured data, such as settings, language translations, etc. It is very similar to YAML. The plugin implements custom language. Easy implementation for Go to PHP classes and completion for classes. | [Neon web](https://ne-on.org/) | [intellij-neon](https://github.com/nette-intellij/intellij-neon) | [Neon plugin](https://plugins.jetbrains.com/plugin/7060-neon-support) | +| Nette Tester | Nette Tester is a simple and yet convenient PHP code testing tool. The plugin implements "run configurations" and "run line markers". Supports run configurations in a remote interpreter (eg: in Docker or docker-compose) | [Tester web](https://tester.nette.org/en/) | [intellij-nette-tester](https://github.com/nette-intellij/intellij-nette-tester) | [Tester plugin](https://plugins.jetbrains.com/plugin/8226-nette-tester) | ## PHP Annotations The PHP Annotations plugin extends PhpStorm to support annotations in PHPDoc blocks. * [PHP Annotations in PhpStorm Plugins Repository](https://plugins.jetbrains.com/plugin/7320-php-annotations) -* [GitHub](https://github.com/Haehnchen/idea-php-annotation-plugin) \ No newline at end of file +* [GitHub](https://github.com/Haehnchen/idea-php-annotation-plugin) diff --git a/products/phpstorm/php_open_api.md b/products/phpstorm/php_open_api.md index 6eb548740..f19cd6187 100644 --- a/products/phpstorm/php_open_api.md +++ b/products/phpstorm/php_open_api.md @@ -34,21 +34,21 @@ Interface: * Extension point to implement to provide Type information on various PhpPsiElements */ public interface PhpTypeProvider2 { - + ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.php.typeProvider2"); - + /** - * @return Your custom signature key, i.e. "?". Do not use any of PhpTypeSignatureKey.XXX constants though! + * @return Your custom signature key, i.e. "?". Do not use any of PhpTypeSignatureKey.XXX constants though! */ char getKey(); - + /** * @param element to deduce type for - using only LOCAL info. THIS IS MOST CRUCIAL ASPECT TO FOLLOW - * @return type for element, null if no insight. You can return a custom signature here to be later decoded by method below. + * @return type for element, null if no insight. You can return a custom signature here to be later decoded by the method below. */ @Nullable String getType(PsiElement element); - + /** * @param expression Signature expression to decode. You can use PhpIndex.getBySignature() to look up expression internals. * @param project well so you can reach the PhpIndex @@ -62,15 +62,15 @@ Our implementation: includes a Completion contributor for the parameter values t ```java public class PhpStaticFactoryTypeProvider extends CompletionContributor implements PhpTypeProvider2 { - + private static final Key>>> STATIC_FACTORY_TYPE_MAP = new Key>>>("STATIC_FACTORY_TYPE_MAP"); - + @Override public char getKey() { return 'S'; } - + @Nullable @Override public String getType(PsiElement e) { @@ -90,7 +90,7 @@ public class PhpStaticFactoryTypeProvider extends CompletionContributor implemen } return null; } - + @Override public Collection getBySignature(String expression, Project project) { Map> methods = getStaticMethodTypesMap(project); @@ -103,7 +103,7 @@ public class PhpStaticFactoryTypeProvider extends CompletionContributor implemen } return Collections.emptySet(); } - + synchronized Map> getStaticMethodTypesMap(final Project project) { CachedValue>> myStaticMethodTypesMap = project.getUserData(STATIC_FACTORY_TYPE_MAP); if (myStaticMethodTypesMap == null) { @@ -158,7 +158,7 @@ public class PhpStaticFactoryTypeProvider extends CompletionContributor implemen } return myStaticMethodTypesMap.getValue(); } - + private static Collection getVariables(Project project, final String key) { PsiFile file = getMetaFile(project); final Collection result = new SmartList(); @@ -179,12 +179,12 @@ public class PhpStaticFactoryTypeProvider extends CompletionContributor implemen } return result; } - + public static PsiFile getMetaFile(Project project) { VirtualFile metaFile = LocalFileSystem.getInstance().findFileByPath(project.getBasePath() + File.separatorChar + ".phpstorm.meta.php"); return metaFile != null ? PsiManager.getInstance(project).findFile(metaFile) : null; } - + @Override public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) { final ProcessingContext context = new ProcessingContext(); @@ -194,7 +194,7 @@ public class PhpStaticFactoryTypeProvider extends CompletionContributor implemen .accepts(position, context)) { ParameterListOwner parameterListOwner = PsiTreeUtil.getStubOrPsiParentOfType(position, ParameterListOwner.class); if (parameterListOwner instanceof MethodReference && ((MethodReference)parameterListOwner).isStatic()) { - + Map map = getStaticMethodTypesMap(position.getProject()).get(((MethodReference)parameterListOwner).getSignature()); for (String s : map.keySet()) { result.addElement(LookupElementBuilder.create(s).appendTailText(map.get(s), true)); @@ -206,8 +206,8 @@ public class PhpStaticFactoryTypeProvider extends CompletionContributor implemen } ``` -to make completion work registration is required: +To make completion work registration is required: ```xml -``` \ No newline at end of file +``` diff --git a/products/phpstorm/php_open_api_breaking_changes.md b/products/phpstorm/php_open_api_breaking_changes.md index acefd1dfd..4263fa081 100644 --- a/products/phpstorm/php_open_api_breaking_changes.md +++ b/products/phpstorm/php_open_api_breaking_changes.md @@ -1,16 +1,16 @@ --- -title: Breaking Changes +title: Breaking Changes --- ## Union Types Support -PhpStorm 2020.2 introduced support for [PHP union types](https://wiki.php.net/rfc/union_types_v2), which resulted in some PSI-breaking changes. +PhpStorm 2020.2 introduced support for [PHP union types](https://wiki.php.net/rfc/union_types_v2), which resulted in some PSI-breaking changes. In earlier versions, type hints in parameters, properties, and return types were parsed inconsistently: -* Return types used a separate `PhpReturnType` wrapper element, which contained the nullability question mark and the class reference of the actual type. -* Parameters and properties used no wrapper element: class references together with nullability question mark were plain children of `Parameter` or `CLASS_FIELDS`. +* Return types used a separate `PhpReturnType` wrapper element, which contained the nullability question mark and the actual type's class reference. +* Parameters and properties used no wrapper element: class references and nullability question mark were plain children of `Parameter` or `CLASS_FIELDS`. -As of PhpStorm 2020.2, class references with the question mark are uniformly wrapped into the `PhpTypeDeclaration` element, which is the parent for `PhpReturnType`, `PhpFieldType`, and `PhpParameterType`. +As of PhpStorm 2020.2, class references with the question mark are uniformly wrapped into the `PhpTypeDeclaration` element, which is the parent for `PhpReturnType`, `PhpFieldType`, and `PhpParameterType`. If your existing code fetches a class reference directly from the parent element, it is now required to get `PhpTypeDeclaration` first, and then call `PhpTypeDeclaration#getClassReferences()`. @@ -23,7 +23,7 @@ private void handleParameterBefore(Parameter parameter) { } ``` -After 2020.2: +After 2020.2: ```java private void handleParameterAfter(Parameter parameter) { @@ -35,7 +35,8 @@ After 2020.2: ``` ## Deprecated `PhpReturnType.getClassReference()` -As of PhpStorm 2020.2, `PhpReturnType.getClassReference()` is deprecated, since there can be multiple class references. This method also became nullable, since in earlier versions an incomplete `?` type was parsed just as a question mark, but now it is parsed as `PhpTypeDeclaration` with empty `getClassReferences()`. +As of PhpStorm 2020.2, `PhpReturnType.getClassReference()` is deprecated, since there can be multiple class references. +This method also became nullable, since in earlier versions an incomplete `?` type was parsed just as a question mark, but now it is parsed as `PhpTypeDeclaration` with empty `getClassReferences()`. Before 2020.2: diff --git a/products/phpstorm/phpstorm.md b/products/phpstorm/phpstorm.md index f28e32cc4..52214b373 100644 --- a/products/phpstorm/phpstorm.md +++ b/products/phpstorm/phpstorm.md @@ -8,8 +8,8 @@ redirect_from: ## Introduction -[PhpStorm](https://www.jetbrains.com/phpstorm/) is an IntelliJ Platform-based product. -Plugins for PhpStorm are developed in Java using the Ultimate edition of IntelliJ IDEA. +[PhpStorm](https://www.jetbrains.com/phpstorm/) is an IntelliJ Platform-based product. +Plugins for PhpStorm are developed in Java using the Ultimate edition of IntelliJ IDEA. The [PsiViewer plugin](https://plugins.jetbrains.com/plugin/227-psiviewer) is also recommended. This page describes configuring plugin projects targeting PhpStorm. @@ -39,7 +39,7 @@ To see how these attributes appear in the `build.gradle` file for PhpStorm, see | [`intellij.plugins`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#intellij-platform-properties) | `com.jetbrains.php:193.5233.102` for the PHP plugin.
See below for PHP plugin version information. | | [`runIde.ideDirectory`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#running-dsl) | Path to locally installed target version of PhpStorm. For example, on macOS:
`/Users//Library/Application Support/JetBrains/Toolbox/apps/PhpStorm/ch-0/193.5233.101/PhpStorm.app/Contents` | -The version of the PHP plugin is explicitly declared because it isn't bundled with IntelliJ IDEA Ultimate Edition. -Select a [version](https://plugins.jetbrains.com/plugin/6610-php/versions) of the PHP plugin that is compatible with the `intellij.version`. +The PHP plugin version is explicitly declared because it isn't bundled with IntelliJ IDEA Ultimate Edition. +Select a [version](https://plugins.jetbrains.com/plugin/6610-php/versions) of the PHP plugin compatible with the `intellij.version`. The dependency on the PHP plugin APIs must be declared in the `plugin.xml` file, as shown in the tutorial [Configuring plugin.xml](/products/dev_alternate_products.md#configuring-pluginxml) section. diff --git a/products/pycharm.md b/products/pycharm.md index c100e3dd3..12d9d51b3 100644 --- a/products/pycharm.md +++ b/products/pycharm.md @@ -35,7 +35,7 @@ These plugins include the modules `openapi` and `python-psi-api`. These are considered stable APIs, but care should be taken to test your plugin with any version of PyCharm you wish to support. ## Additional Articles and Resources -* [Webinar Recording: “Live Development of a PyCharm Plugin” with Joachim Ansorg](https://blog.jetbrains.com/pycharm/2019/01/webinar-recording-live-development-of-a-pycharm-plugin-with-joachim-ansorg/) +* [Webinar Recording: "Live Development of a PyCharm Plugin" with Joachim Ansorg](https://blog.jetbrains.com/pycharm/2019/01/webinar-recording-live-development-of-a-pycharm-plugin-with-joachim-ansorg/) ## Open Source Plugins for PyCharm When learning new development configurations, it is helpful to have some representative projects for reference: diff --git a/products/rider.md b/products/rider.md index 69dffc52e..ab8fe6c30 100644 --- a/products/rider.md +++ b/products/rider.md @@ -3,27 +3,27 @@ title: Rider Plugin Development --- -## Introduction +## Introduction Rider plugins are generally used to expose the functionality of a ReSharper plugin. -[Rider](https://www.jetbrains.com/rider/) uses the IntelliJ Platform somewhat [differently](/intro/intellij_platform.md#rider) than other Platform-based based IDEs. +[Rider](https://www.jetbrains.com/rider/) uses the IntelliJ Platform somewhat [differently](/intro/intellij_platform.md#rider) than other Platform-based based IDEs. Rider uses the IntelliJ Platform to provide the user interface for a C# and .NET IDE but uses ReSharper to provide the language-specific features. > **TIP** Qualifying Open Source projects can [apply for free licenses](https://www.jetbrains.com/community/opensource/) of JetBrains products. ## IntelliJ IDEA Configuration for Rider Plugin Development -Although there is no dedicated Rider SDK, the [ReSharper DevGuide](https://www.jetbrains.com/help/resharper/sdk/Products/Rider.html) addresses the subject of plugins for Rider. +Although there is no dedicated Rider SDK, the [ReSharper DevGuide](https://www.jetbrains.com/help/resharper/sdk/Products/Rider.html) addresses the subject of plugins for Rider. The documentation describes the [configuration](https://www.jetbrains.com/help/resharper/sdk/Products/Rider.html#plugin-project-jvm) of `build.gradle` and `settings.gradle` files to build a Rider plugin using the [Gradle project system](/tutorials/build_system.md) in IntelliJ IDEA. ## Developing Rider Plugins with the IDEA and ReSharper SDKs -Before starting a new Rider plugin project, review the article [Writing plugins for ReSharper and Rider](https://blog.jetbrains.com/dotnet/2019/02/14/writing-plugins-resharper-rider/). -In particular, this article discusses _One Template to Rule Them All_, a way to quickly get started writing plugins for both Rider and ReSharper. +Before starting a new Rider plugin project, review the article [Writing plugins for ReSharper and Rider](https://blog.jetbrains.com/dotnet/2019/02/14/writing-plugins-resharper-rider/). +In particular, this article discusses _One Template to Rule Them All_, a way to quickly get started writing plugins for both Rider and ReSharper. -More background information is available in the [Building a .NET IDE with JetBrains Rider](https://www.codemag.com/Article/1811091/Building-a-.NET-IDE-with-JetBrains-Rider) article, which includes a high-level description of the _Rider Protocol_ communication process between Rider and ReSharper. +More background information is available in the [Building a .NET IDE with JetBrains Rider](https://www.codemag.com/Article/1811091/Building-a-.NET-IDE-with-JetBrains-Rider) article, which includes a high-level description of the _Rider Protocol_ communication process between Rider and ReSharper. The article is a good counterpoint to the ReSharper DevGuide content, which discusses the protocol at the code level. - + ## Open Source Rider Plugins -When learning new development configurations it is helpful to have some existing plugins for reference. -This list is intended to provide some representative projects. +When learning new development configurations, it is helpful to have some existing plugins for reference. +This list is intended to provide some representative projects. * [Unity support for both ReSharper and Rider](https://github.com/JetBrains/resharper-unity) * [F# support in JetBrains Rider](https://github.com/JetBrains/fsharp-support) * [AgentMulder](https://github.com/ERNICommunity/AgentMulder/) @@ -39,4 +39,4 @@ This list is intended to provide some representative projects. * [StyleCop](https://github.com/StyleCop/StyleCop.ReSharper/) * [TestLinker](https://github.com/matkoch/TestLinker/) * [Xao](https://github.com/hmemcpy/ReSharper.Xao/) -* [Azure Toolkit for Rider](https://github.com/JetBrains/azure-tools-for-intellij) \ No newline at end of file +* [Azure Toolkit for Rider](https://github.com/JetBrains/azure-tools-for-intellij) diff --git a/products/rubymine.md b/products/rubymine.md index bc15ef693..1a4a27ddb 100644 --- a/products/rubymine.md +++ b/products/rubymine.md @@ -12,7 +12,7 @@ Plugin projects for RubyMine can be developed using IntelliJ IDEA with the `grad ## Configuring Plugin Projects Targeting RubyMine The configuration of RubyMine plugin projects follows the methods described in [Configuring Plugin Projects using the IntelliJ IDEA Product Attribute](dev_alternate_products.md#configuring-plugin-projects-using-the-intellij-idea-product-attribute), and [Configuring the plugin.xml File](dev_alternate_products.md#configuring-pluginxml). -The table below summarizes the `gradle-intellij-plugin` attributes to set in the `build.gradle` file for a RubyMine plugin project. +The table below summarizes the `gradle-intellij-plugin` attributes to set in the `build.gradle` file for a RubyMine plugin project. Click on an entry in the table's *Attribute* column to go to the documentation about that attribute. To see how these attributes appear in a similar `build.gradle` file for PhpStorm, see [Configuring build.gradle using the IntelliJ IDEA Product Attribute](/products/dev_alternate_products.md#configuring-buildgradle-using-the-intellij-idea-product-attribute). @@ -24,8 +24,8 @@ To see how these attributes appear in a similar `build.gradle` file for PhpStorm | [`runIde.ideDirectory`](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#running-dsl) | Path to locally installed target version of RubyMine. For example, on macOS:
`/Users//Library/Application Support/JetBrains/Toolbox/apps/RubyMine/ch-0/192.7142.37/RubyMine.app/Contents` | The required `org.jetbrains.plugins.ruby` plugin isn't compatible with IntelliJ IDEA Community edition but is compatible with IntelliJ IDEA Ultimate (`IU`) edition. -Product compatibility is determined from the Ruby plugin [version page](https://plugins.jetbrains.com/plugin/1293-ruby/versions). -The Ruby plugin isn't bundled with `IU`, so the Ruby plugin version must be explicitly declared to support the target RubyMine (and `IU`) BRANCH.BUILD version. +Product compatibility is determined from the Ruby plugin [version page](https://plugins.jetbrains.com/plugin/1293-ruby/versions). +The Ruby plugin isn't bundled with `IU`, so the Ruby plugin version must be explicitly declared to support the target RubyMine (and `IU`) BRANCH.BUILD version. The correct Ruby plugin version is also determined from the Ruby plugin version page. The dependency on the Ruby plugin APIs must be declared in the `plugin.xml` file. @@ -34,7 +34,7 @@ The dependency declaration is illustrated in the `plugin.xml` snippet below: ```xml - com.intellij.modules.ruby + com.intellij.modules.ruby ``` ## Available RubyMine APIs @@ -45,4 +45,4 @@ Test your plugin with any version of RubyMine you intend to support. When learning new APIs, it is helpful to have some representative projects for reference: * [Ruby-Doc-Adder](https://github.com/aristotll/RubyDocAdder) * [Ruby Dynamic Code Insight](https://github.com/JetBrains/ruby-type-inference) -* [Railways](https://github.com/basgren/railways) \ No newline at end of file +* [Railways](https://github.com/basgren/railways) diff --git a/products/webstorm.md b/products/webstorm.md index e2fdc85cd..392a63667 100644 --- a/products/webstorm.md +++ b/products/webstorm.md @@ -25,7 +25,7 @@ To see how these attributes appear in a similar `build.gradle` file for PhpStorm The dependency on the WebStorm APIs must be declared in the `plugin.xml` file. As described in [Modules Specific to Functionality](/basics/getting_started/plugin_compatibility.md#modules-specific-to-functionality) table, the `` tags must declare `JavaScriptLanguage`. -**Note** that for WebStorm the plugin.xml file must also declare a dependency on `com.intellij.modules.platform` because `JavaScriptLanguage` is not recognized as a module. +**Note** that for WebStorm, the plugin.xml file must also declare a dependency on `com.intellij.modules.platform` because `JavaScriptLanguage` is not recognized as a module. Consequently, without the `com.intellij.modules.platform` declaration the plugin is assumed to be a [legacy plugin](/basics/getting_started/plugin_compatibility.md#declaring-plugin-dependencies) and will not load in WebStorm. ## Available WebStorm APIs @@ -34,7 +34,7 @@ Test your plugin with any version of WebStorm you wish to support. ## Open Source Plugins for WebStorm When learning new plugin development it is helpful to have some representative projects for reference: -* [JS Toolbox](https://github.com/andresdominguez/jsToolbox) -* [Require.​js](https://github.com/Fedott/WebStormRequireJsPlugin) +* [JS Toolbox](https://github.com/andresdominguez/jsToolbox) +* [Require.js](https://github.com/Fedott/WebStormRequireJsPlugin) * [deep-js-completion](https://github.com/klesun/deep-js-completion) * [Run Configuration for TypeScript](https://plugins.jetbrains.com/plugin/10841-run-configuration-for-typescript) diff --git a/reference_guide/api_changes/api_changes_list_2016.md b/reference_guide/api_changes/api_changes_list_2016.md index cdd7fae8c..2a016a633 100644 --- a/reference_guide/api_changes/api_changes_list_2016.md +++ b/reference_guide/api_changes/api_changes_list_2016.md @@ -4,12 +4,12 @@ title: Incompatible Changes in IntelliJ Platform and Plugins API 2016.* Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on how to verify compatibility. -## 2016.3 +## 2016.3 ### Changes in IntelliJ Platform 2016.3 @@ -17,7 +17,7 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h : Implement this method or extend [`com.intellij.openapi.application.ApplicationAdapter`](upsource:////platform/core-api/src/com/intellij/openapi/application/ApplicationAdapter.java) class instead of implementing the interface. -## 2016.2 +## 2016.2 ### Changes in IntelliJ Platform 2016.2 @@ -28,4 +28,4 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h : [`com.intellij.util.net.HttpConfigurable.getPlainProxyPassword()`](upsource:///platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java) instead. `org.jetbrains.asm4` package removed -: Use classes from `org.jetbrains.org.objectweb.asm` package instead. \ No newline at end of file +: Use classes from `org.jetbrains.org.objectweb.asm` package instead. diff --git a/reference_guide/api_changes/api_changes_list_2017.md b/reference_guide/api_changes/api_changes_list_2017.md index 3b754b662..0d654e9a6 100644 --- a/reference_guide/api_changes/api_changes_list_2017.md +++ b/reference_guide/api_changes/api_changes_list_2017.md @@ -4,33 +4,33 @@ title: Incompatible Changes in IntelliJ Platform and Plugins API 2017.* Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on how to verify compatibility. > **NOTE** Changes from API marked with `org.jetbrains.annotations.ApiStatus.@Experimental`/`ScheduledForRemoval` are not listed here, as incompatible changes are to be expected. -## 2017.3 +## 2017.3 ### Changes in IntelliJ Platform 2017.3 `com.intellij.internal.statistic.AbstractApplicationUsagesCollector` class removed -: This class isn't supposed to be used in regular plugins. Override `com.intellij.internal.statistic.AbstractProjectsUsagesCollector` instead if you're developing an IDE with its own statistics services. - -`com.intellij.internal.statistic.UsagesCollector.doPersistProjectUsages` method removed +: This class isn't supposed to be used in regular plugins. Override `com.intellij.internal.statistic.AbstractProjectsUsagesCollector` instead if you're developing an IDE with its own statistics services. + +`com.intellij.internal.statistic.UsagesCollector.doPersistProjectUsages` method removed : This method isn't supposed to be used in regular plugins. There is no need to call this method anymore. - + `org.apache.sanselan` package removed : Use classes from `org.apache.commons.imaging` instead. - -`com.intellij.psi.MultiplePsiFilesPerDocumentFileViewProvider.getLanguages` abstract method added -: Implementation of this class are supposed to have several languages so you need to implement this method explicitly and return them all. - -`org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator.changeCoroutineConfiguration` abstract method added -: You need to implement this method and add the logic for updating the configuration in your build system. - -`org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator.updateLanguageVersion` abstract method added + +`com.intellij.psi.MultiplePsiFilesPerDocumentFileViewProvider.getLanguages` abstract method added +: An implementation of this class is supposed to have several languages, so you need to explicitly implement the method and return them all. + +`org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator.changeCoroutineConfiguration` abstract method added +: You need to implement this method and add the logic for updating the configuration in your build system. + +`org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator.updateLanguageVersion` abstract method added : You need to implement this method and add the logic for updating the configuration in your build system. `org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator.addLibraryDependency` abstract method added @@ -56,4 +56,4 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h ### Changes in PhpStorm and PHP Plugin 2017.3 `com.jetbrains.php.lang.psi.elements.Function.getReturnType()` method return type changed from `PsiElement` to `PhpReturnType` -: Before method had been returning a `com.jetbrains.php.lang.psi.elements.ClassReference`. Now method returns `com.jetbrains.php.lang.psi.elements.PhpReturnType`. Method `ReturnType.getClassReference()` can be used if you need just a `ClassReference`. If you need to get the `PhpType`, use `com.jetbrains.php.lang.psi.elements.Function.getReturnType.getType()` method instead. \ No newline at end of file +: Before method had been returning a `com.jetbrains.php.lang.psi.elements.ClassReference`. Now method returns `com.jetbrains.php.lang.psi.elements.PhpReturnType`. Method `ReturnType.getClassReference()` can be used if you need just a `ClassReference`. If you need to get the `PhpType`, use `com.jetbrains.php.lang.psi.elements.Function.getReturnType.getType()` method instead. diff --git a/reference_guide/api_changes/api_changes_list_2018.md b/reference_guide/api_changes/api_changes_list_2018.md index a1b6de9b6..05806c4b5 100644 --- a/reference_guide/api_changes/api_changes_list_2018.md +++ b/reference_guide/api_changes/api_changes_list_2018.md @@ -5,9 +5,9 @@ title: Incompatible Changes in IntelliJ Platform and Plugins API 2018.* @@ -15,7 +15,7 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h > **NOTE** Changes from API marked with `org.jetbrains.annotations.ApiStatus.@Experimental`/`ScheduledForRemoval` are not listed here, as incompatible changes are to be expected. -## 2018.3 +## 2018.3 ### Changes in IntelliJ Platform 2018.3 @@ -45,7 +45,7 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h ## 2018.2 - + ### Changes in IntelliJ Platform 2018.2 `com.intellij.util.Query.forEach` method parameter type changed from `Processor` to `Processor` @@ -63,17 +63,17 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h `com.intellij.util.InstanceofQuery` class type parameter `T` added : Set this parameter at call sites to base query type. -`com.intellij.task.ProjectTaskManager.build` method parameter type changed from `Artifact[]` to `ProjectModelBuildableElement[]` +`com.intellij.task.ProjectTaskManager.build` method parameter type changed from `Artifact[]` to `ProjectModelBuildableElement[]` : In most of the cases, it's enough to recompile the code. -`com.intellij.task.ProjectTaskManager.rebuild` method parameter type changed from `Artifact[]` to `ProjectModelBuildableElement[]` +`com.intellij.task.ProjectTaskManager.rebuild` method parameter type changed from `Artifact[]` to `ProjectModelBuildableElement[]` : In most of the cases, it's enough to recompile the code. -`org.apache.batik.script.InterpreterFactory.createInterpreter` abstract method added +`org.apache.batik.script.InterpreterFactory.createInterpreter` abstract method added : Update `InterpreterFactory` implementations accordingly. -## 2018.1 +## 2018.1 ### Changes in IntelliJ Platform 2018.1 @@ -83,27 +83,27 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h `com.google.common.util.concurrent.Futures.get` method removed : Use `com.google.common.util.concurrent.Futures.getChecked` instead. -[`org.tmatesoft.svn`](https://svnkit.com/index.html) package removed +[`org.tmatesoft.svn`](https://svnkit.com/index.html) package removed : Use classes from `org.jetbrains.idea.svn` instead. `org.jetbrains.idea.svn.svnkit.SvnKitManager` class removed : Use `org.jetbrains.idea.svn.api.ClientFactory` instead. -`clojure` package removed -: Clojure 1.8 jars are removed from IntelliJ Ultimate package, provide your own jars if needed. +`clojure` package removed +: Clojure 1.8 jars are removed from the IntelliJ Ultimate package; provide your own jars if needed. -`com.intellij.ide.structureView.newStructureView.StructureViewComponent.getTreeBuilder` method removed +`com.intellij.ide.structureView.newStructureView.StructureViewComponent.getTreeBuilder` method removed : Use `queueUpdate` and `getTree` instead. ### Changes in PhpStorm and PHP Plugin 2018.1 -`com.jetbrains.php.lang.documentation.phpdoc.parser.PhpDocElementTypes.DOC_COMMENT` field type changed from `com.intellij.psi.tree.ILazyParseableElementType` to `com.jetbrains.php.lang.documentation.phpdoc.psi.stubs.PhpDocCommentElementType` +`com.jetbrains.php.lang.documentation.phpdoc.parser.PhpDocElementTypes.DOC_COMMENT` field type changed from `com.intellij.psi.tree.ILazyParseableElementType` to `com.jetbrains.php.lang.documentation.phpdoc.psi.stubs.PhpDocCommentElementType` : In most of the cases, it's enough to recompile the code. It may also be needed to check that the code doesn't rely on the field's type. `com.jetbrains.php.lang.documentation.phpdoc.parser.PhpDocElementTypes.phpDocSpecialTag` field type changed from `com.intellij.psi.tree.ILazyParseableElementType` to `com.jetbrains.php.lang.documentation.phpdoc.psi.stubs.PhpDocMethodTagElementType` : In most of the cases, it's enough to recompile the code. It may also be needed to check that the code doesn't rely on the field's type. -`com.jetbrains.php.lang.documentation.phpdoc.parser.PhpDocElementTypes.phpDocTag` field type changed from `com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocElementType` to `com.jetbrains.php.lang.documentation.phpdoc.psi.stubs.PhpDocTagElementType` +`com.jetbrains.php.lang.documentation.phpdoc.parser.PhpDocElementTypes.phpDocTag` field type changed from `com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocElementType` to `com.jetbrains.php.lang.documentation.phpdoc.psi.stubs.PhpDocTagElementType` : In most of the cases, it's enough to recompile the code. It may also be needed to check that the code doesn't rely on the field's type. `com.jetbrains.php.lang.documentation.phpdoc.parser.PhpDocElementTypes.phpDocReturn` field type changed from `com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocElementType` to `com.jetbrains.php.lang.documentation.phpdoc.psi.stubs.PhpDocTagElementType` @@ -141,4 +141,3 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h `com.jetbrains.php.lang.documentation.phpdoc.psi.impl.tags.PhpDocMethodImpl` superclass changed from `com.jetbrains.php.lang.documentation.phpdoc.psi.impl.PhpDocPsiElementImpl` to `com.jetbrains.php.lang.psi.elements.impl.PhpNamedElementImpl` : It's necessary to check that the code doesn't rely on the superclass. - diff --git a/reference_guide/api_changes/api_changes_list_2019.md b/reference_guide/api_changes/api_changes_list_2019.md index 7ab292867..276663b07 100644 --- a/reference_guide/api_changes/api_changes_list_2019.md +++ b/reference_guide/api_changes/api_changes_list_2019.md @@ -4,7 +4,58 @@ title: Incompatible Changes in IntelliJ Platform and Plugins API 2019.* Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on how to verify compatibility. @@ -52,7 +103,7 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h : See `BuildNumber.asString`, `BuildNumber.getBaselineVersion()` and `BuildNumber.getComponents()` as alternatives. `com.intellij.remoteServer.configuration.deployment.DeploymentConfigurationManager.createAndRunConfiguration(ServerType, RemoteServer)` method removed -: Use `DeploymentConfigurationManager.createAndRunConfiguration(ServerType, RemoteServer, DeploymentSourceType)` instead. +: Use `DeploymentConfigurationManager.createAndRunConfiguration(ServerType, RemoteServer, DeploymentSourceType)` instead. #### VCS `com.intellij.openapi.vcs.changes.ui.ChangesListView.UNVERSIONED_FILES_DATA_KEY` field removed @@ -93,17 +144,17 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h ### Changes in Cucumber Plugin 2019.3 `org.jetbrains.plugins.cucumber.javascript.CucumberJavaScriptStepDefinitionCreator#createStepDefinition(GherkinStep, PsiFile)` method removed -: Use `org.jetbrains.plugins.cucumber.javascript.CucumberJavaScriptStepDefinitionCreator#createStepDefinition(GherkinStep, PsiFile, boolean)` instead. - +: Use `org.jetbrains.plugins.cucumber.javascript.CucumberJavaScriptStepDefinitionCreator#createStepDefinition(GherkinStep, PsiFile, boolean)` instead. + `org.jetbrains.plugins.cucumber.psi.GherkinStep#getStepName()` method removed -: Use `org.jetbrains.plugins.cucumber.psi.GherkinStep#getName()` instead. - +: Use `org.jetbrains.plugins.cucumber.psi.GherkinStep#getName()` instead. + `org.jetbrains.plugins.cucumber.CucumberJvmExtensionPoint#resolveStep()` method removed -: See `org.jetbrains.plugins.cucumber.steps.reference.CucumberStepReference#multiResolveInner()` instead. +: See `org.jetbrains.plugins.cucumber.steps.reference.CucumberStepReference#multiResolveInner()` instead. `org.jetbrains.plugins.cucumber.CucumberJvmExtensionPoint#getGlues()` method removed -: Java specific method was moved to CucumberJava implementation. - +: Java specific method was moved to CucumberJava implementation. + ### Changes in DataGrip and Database Tools Plugin 2019.3 `com.intellij.sql.dialects.mssql.MssqlDialect` class renamed to `com.intellij.sql.dialects.mssql.MsDialect` @@ -143,7 +194,7 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h : Use `com.jetbrains.python.PyPsiBundle` instead. -## 2019.2 +## 2019.2 ### Changes in IntelliJ Platform 2019.2 Constructor injection referring to extension points not supported @@ -159,14 +210,14 @@ Constructor injection referring to extension points not supported : [Java-WebSocket](https://github.com/TooTallNate/Java-WebSocket) library was removed, bundle it with your plugin instead. `com.intellij.ui.layout.Cell.invoke$default(Cell, JComponent, CCFlags[], int, GrowPolicy, String, int, Object)` method parameter type changed -: Signature of this function has been seriously changed without possibility to keep the old function. Change invocations and overriding of that function according to new parameters and recompile the code. +: The signature of this function has been seriously changed without the possibility to keep the old function. Change invocations and overriding of that function according to new parameters and recompile the code. `com.intellij.ui.layout.Row.label$default(Row, String, int, UIUtil.ComponentStyle, UIUtil.FontColor, boolean, int, Object)` method removed : This method has been pulled up to the base class `Cell`; since it has default parameters, it's a binary breaking change in Kotlin. Recompile your code to pick up the new signature. `com.yourkit` package removed -: YourKit library has been extracted into the separate plugin which is not bundled in all IDEs by default. YourKit library is a library for profiling IDE, and its util classes shouldn't be used for general purpose. Instead of `com.yourkit.util.Strings` please use `org.apache.commons.lang.StringUtils`. Instead of `com.yourkit.util.ArrayUtil` please use `org.apache.commons.lang.ArrayUtils`. +: YourKit library has been extracted into the separate plugin, which is not bundled in all IDEs by default. YourKit library is a library for profiling IDE, and its util classes shouldn't be used for general purposes. Instead of `com.yourkit.util.Strings` please use `org.apache.commons.lang.StringUtils`. Instead of `com.yourkit.util.ArrayUtil` please use `org.apache.commons.lang.ArrayUtils`. `org.jetbrains.intellij.build.ProductProperties.yourkitAgentBinariesDirectoryPath` field removed : Please bundle [performanceTesting plugin](https://plugins.jetbrains.com/plugin/7819-performance-testing) in case you would like to bundle YourKit profiler within your IDE. @@ -197,13 +248,13 @@ Recompile your code to pick up the new signature. ## 2019.1 - + ### Changes in IntelliJ Platform 2019.1 -`kotlinx.coroutines.experimental` package removed -: Bundled Kotlin library is updated to 1.3 so the plugins must [migrate](https://blog.jetbrains.com/kotlin/2018/09/kotlin-1-3-rc-is-here-migrate-your-coroutines/) to the stable versions of coroutines. +`kotlinx.coroutines.experimental` package removed +: Bundled Kotlin library is updated to 1.3, so the plugins must [migrate](https://blog.jetbrains.com/kotlin/2018/09/kotlin-1-3-rc-is-here-migrate-your-coroutines/) to the stable versions of coroutines. -`com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl(Project, FileStatusManager, FileIndexFacade, ProjectManager, DefaultVcsRootPolicy, VcsFileListenerContextHelper)` constructor removed +`com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl(Project, FileStatusManager, FileIndexFacade, ProjectManager, DefaultVcsRootPolicy, VcsFileListenerContextHelper)` constructor removed : Use `com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl.(Project, FileStatusManager, FileIndexFacade, ProjectManager, DefaultVcsRootPolicy)`. `com.intellij.injected.editor.DocumentWindow.injectedToHost(int, boolean)` abstract method added diff --git a/reference_guide/api_changes/api_changes_list_2020.md b/reference_guide/api_changes/api_changes_list_2020.md index b62fd5fce..7e7927aee 100644 --- a/reference_guide/api_changes/api_changes_list_2020.md +++ b/reference_guide/api_changes/api_changes_list_2020.md @@ -4,13 +4,11 @@ title: Incompatible Changes in IntelliJ Platform and Plugins API 2020.* Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on how to verify compatibility. @@ -68,9 +66,14 @@ Please see [Incompatible API Changes](/reference_guide/api_changes_list.md) on h ### Changes in IntelliJ Platform 2020.3 +The PSI structure of multi-dimensional arrays in Java source files changed (see `com.intellij.psi.PsiTypeElement`) +: Now the children are flattened: brackets for all the dimensions are direct children of the `PsiTypeElement` that represent the multi-dimensional array. This change doesn't break source or binary compatibility but may produce behavioral changes in the code that traverses the tree of Java source files. + +The `com.intellij.psi.PsiAnnotation.getOwner` method now returns `PsiType` instead of `PsiTypeElement` for type annotations in Java source files +: This change supports identifying whether a type annotation is attached to an inner class or a particular dimension of a multi-dimensional array. +This change doesn't break source or binary compatibility but may produce behavioral changes for callers. `com.intellij.openapi.application.NonBlockingReadAction.finishOnUiThread` method parameter type changed from ``Consumer`` to ``Consumer`` : This may break source-compatibility with inheritors written in Kotlin. - ### Changes in Java Plugin 2019.3 The PSI structure of multi-dimensional arrays in Java source files changed (see `com.intellij.psi.PsiTypeElement`) @@ -79,7 +82,6 @@ The PSI structure of multi-dimensional arrays in Java source files changed (see The `com.intellij.psi.PsiAnnotation.getOwner` method now returns `PsiType` instead of `PsiTypeElement` for type annotations in Java source files : This change supports identifying whether a type annotation is attached to an inner class or a particular dimension of a multi-dimensional array. This change doesn't break source or binary compatibility but may produce behavioral changes for callers. - ### Changes in Python Plugin 2020.3 All parameters in `com.jetbrains.python.psi.PyElementVisitor` marked `@NotNull` @@ -91,10 +93,10 @@ All parameters in `com.jetbrains.python.psi.PyElementVisitor` marked `@NotNull` ### Changes in IntelliJ Platform 2020.2 Support for JavaFX deprecated -: Plugins should migrate to [JCEF](/reference_guide/jcef.md). Alternatively, add an explicit dependency on [JavaFX Runtime for Plugins](https://plugins.jetbrains.com/plugin/14250-javafx-runtime-for-plugins). +: Plugins should migrate to [JCEF](/reference_guide/jcef.md). Alternatively, add an explicit dependency on [JavaFX Runtime for Plugins](https://plugins.jetbrains.com/plugin/14250-javafx-runtime-for-plugins). `com.intellij.psi.util.PsiTreeUtil.processElements(element, processor)` method parameter type changed from `PsiElementProcessor` to `PsiElementProcessor` -: This may break source-compatibility with clients that pass more specific processor. Passing more specific processor was illegal before as well because the `processElements` passes every descendant `PsiElement` to the processor regardless of its type. However, this worked with some poorly written clients, e.g. `PsiElementProcessor.CollectFilteredElements` and `PsiElementProcessor.FindFilteredElement` (both deprecated now). To simplify the migration, a new three-arg `processElements(element, elementClass, processor)` is introduced that actually filters by element class, so in most cases, the simplest migration would be to add a wanted element class as a second argument. However, it's advised to use `SyntaxTraverser` API instead, which is more rich and flexible. +: This may break source-compatibility with clients that pass a more specific processor. Passing a more specific processor was illegal before because the `processElements` passes every descendant `PsiElement` to the processor regardless of its type. However, this worked with some poorly written clients, e.g. `PsiElementProcessor.CollectFilteredElements` and `PsiElementProcessor.FindFilteredElement` (both deprecated now). To simplify the migration, a new three-arg `processElements(element, elementClass, processor)` is introduced that filters by element class. In most cases, the simplest migration would be to add a wanted element class as a second argument. However, it's advised to use `SyntaxTraverser` API instead, which is more rich and flexible. `com.maddyhome.idea.copyright.util.FileTypeUtil.getFileTypeByName(String)` method removed : This was an internal utility method not intended for use in plugins. Use `FileTypeManager.getInstance().findFileTypeByName()` instead. @@ -103,7 +105,7 @@ Support for JavaFX deprecated : [Javassist](https://github.com/jboss-javassist/javassist) library was removed, bundle it with your plugin instead. `com.intellij.compiler.backwardRefs.LanguageCompilerRefAdapter.INSTANCES` field removed -: This field leaked instances of plugin's extensions on plugin unloading. Use `com.intellij.compiler.backwardRefs.LanguageCompilerRefAdapter#EP_NAME.getExtensionList()` directly instead. +: This field leaked instances of plugin's extensions on plugin unloading. Use `com.intellij.compiler.backwardRefs.LanguageCompilerRefAdapter#EP_NAME.getExtensionList()` directly instead. `groovy.util.AntBuilder` class removed : Add `org.codehaus.groovy:groovy-ant` dependency. @@ -154,16 +156,17 @@ Support for JavaFX deprecated : This may break source-compatibility with inheritors written in Kotlin. `com.intellij.pom.java.LanguageLevel.JDK_13_PREVIEW` field removed -: Please remove plugin code supporting Java 13 language level features. IntelliJ IDEA supports preview features of the latest Java release as well as one upcoming release (if available). +: Please remove the plugin code supporting Java 13 language level features. +IntelliJ IDEA supports preview features of the latest Java release and one upcoming release (if available). #### VCS - + `com.intellij.diff.util.DiffUserDataKeysEx.REVISION_INFO` field removed -: Use `com.intellij.diff.DiffVcsDataKeys.REVISION_INFO` instead. +: Use `com.intellij.diff.DiffVcsDataKeys.REVISION_INFO` instead. `com.intellij.codeInsight.actions.FormatChangedTextUtil.getChangedElements(Project, Change[], Function)` method removed -: Use `com.intellij.codeInsight.actions.VcsFacadeImpl.getVcsInstance().getChangedElements(...)` instead. +: Use `com.intellij.codeInsight.actions.VcsFacadeImpl.getVcsInstance().getChangedElements(...)` instead. ### Changes in GitHub Plugin 2020.2 @@ -188,7 +191,7 @@ Support for JavaFX deprecated ### Changes in Java EE Plugins 2020.2 Java EE plugins split -: Plugin `com.intellij.javaee` _Java EE: EJB, JPA, Servlets_ has been split to: +: Plugin `com.intellij.javaee` _Java EE: EJB, JPA, Servlets_ has been split to: - `com.inteellij.javaee` _Java EE Platform_ - main plugin other JavaEE/Jakarta plugins depend on - `com.intellij.javaee.app.servers.integration` _Java EE: Application Servers Integration_ - `com.intellij.javaee.ejb` _Java EE: Enterprise Java Beans (EJB)_ @@ -207,7 +210,7 @@ Java EE plugins split Added Union Types Support : Please see [PhpStorm Breaking Changes](/products/phpstorm/php_open_api_breaking_changes.md). - + ### Changes in Kotlin Plugin 1.4 `org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings.PACKAGES_TO_USE_STAR_IMPORTS` field type changed from `PackageEntryTable` to `KotlinPackageEntryTable` @@ -229,34 +232,34 @@ Added Union Types Support `com.intellij.psi.stubs.PrebuiltStubsProviderBase` class now extends `com.intellij.index.PrebuiltIndexProvider` and inherits its abstract method `getIndexRoot()` : Use `com.intellij.psi.stubs.PlatformPrebuiltStubsProviderBase` instead. -`com.intellij.psi.PsiElementVisitor.visitElement` method `PsiElement` parameter marked `@NotNull` +`com.intellij.psi.PsiElementVisitor.visitElement` method `PsiElement` parameter marked `@NotNull` : This may break source-compatibility with inheritors written in Kotlin if they declare parameter type as nullable. -`com.intellij.psi.PsiElementVisitor.visitFile` method `PsiFile` parameter marked `@NotNull` +`com.intellij.psi.PsiElementVisitor.visitFile` method `PsiFile` parameter marked `@NotNull` : This may break source-compatibility with inheritors written in Kotlin if they declare parameter type as nullable. -`com.intellij.psi.PsiElementVisitor.visitBinaryFile` method `PsiBinaryFile` parameter marked `@NotNull` +`com.intellij.psi.PsiElementVisitor.visitBinaryFile` method `PsiBinaryFile` parameter marked `@NotNull` : This may break source-compatibility with inheritors written in Kotlin if they declare parameter type as nullable. -`com.intellij.psi.PsiElementVisitor.visitPlainTextFile` method `PsiPlainTextFile` parameter marked `@NotNull` +`com.intellij.psi.PsiElementVisitor.visitPlainTextFile` method `PsiPlainTextFile` parameter marked `@NotNull` : This may break source-compatibility with inheritors written in Kotlin if they declare parameter type as nullable. -`com.intellij.psi.PsiElementVisitor.visitErrorElement` method `PsiErrorElement` parameter marked `@NotNull` +`com.intellij.psi.PsiElementVisitor.visitErrorElement` method `PsiErrorElement` parameter marked `@NotNull` : This may break source-compatibility with inheritors written in Kotlin if they declare parameter type as nullable. -`com.intellij.psi.PsiElementVisitor.visitPlainText` method `PsiPlainText` parameter marked `@NotNull` +`com.intellij.psi.PsiElementVisitor.visitPlainText` method `PsiPlainText` parameter marked `@NotNull` : This may break source-compatibility with inheritors written in Kotlin if they declare parameter type as nullable. -`com.intellij.psi.PsiElementVisitor.visitDirectory` method `PsiDirectory` parameter marked `@NotNull` +`com.intellij.psi.PsiElementVisitor.visitDirectory` method `PsiDirectory` parameter marked `@NotNull` : This may break source-compatibility with inheritors written in Kotlin if they declare parameter type as nullable. -`com.intellij.psi.PsiElementVisitor.visitComment` method `PsiComment` parameter marked `@NotNull` +`com.intellij.psi.PsiElementVisitor.visitComment` method `PsiComment` parameter marked `@NotNull` : This may break source-compatibility with inheritors written in Kotlin if they declare parameter type as nullable. -`com.intellij.psi.PsiElementVisitor.visitWhiteSpace` method `PsiWhiteSpace` parameter marked `@NotNull` +`com.intellij.psi.PsiElementVisitor.visitWhiteSpace` method `PsiWhiteSpace` parameter marked `@NotNull` : This may break source-compatibility with inheritors written in Kotlin if they declare parameter type as nullable. -`com.intellij.psi.PsiElementVisitor.visitOuterLanguageElement` method `OuterLanguageElement` parameter marked `@NotNull` +`com.intellij.psi.PsiElementVisitor.visitOuterLanguageElement` method `OuterLanguageElement` parameter marked `@NotNull` : This may break source-compatibility with inheritors written in Kotlin if they declare parameter type as nullable. `com.intellij.codeInspection.unused.ImplicitPropertyUsageProvider.isUsed` method `Property` parameter marked `@NotNull` @@ -266,7 +269,7 @@ Added Union Types Support : Use `com.intellij.testFramework.ReadOnlyLightVirtualFile`-based PSI instead. Java code migrated to use `TYPE_USE` nullability annotations -: Due to some problems in Kotlin compiler existing Kotlin code might become incompilable in rare cases if a method written in Java returning an array and annotated as `@Nullable` or `@NotNull` is used or overridden. +: In rare cases existing Kotlin code might become uncompilable due to some problems in the Kotlin compiler: if a method is used or overridden, and is written in Java, and returns an array annotated as `@Nullable` or `@NotNull`. `com.intellij.navigation.ChooseByNameContributorEx.processNames` method parameter type changed from `Processor` to ``Processor`` : This may break source-compatibility with inheritors written in Kotlin. @@ -278,13 +281,13 @@ Images module functionality (package `org.intellij.images.*`) extracted to plugi : The dependency [must be declared](/basics/plugin_structure/plugin_dependencies.md) explicitly now: * Add `com.intellij.platform.images` in `plugin.xml` * Add to `build.gradle`: - + ```groovy intellij { plugins = ['platform-images'] } ``` - * If your plugin depends on other plugins using `com.intellij.platform.images` (e.g., CSS), please make sure to use `gradle-intellij-plugin` >=0.4.19 + * If your plugin depends on other plugins using `com.intellij.platform.images` (e.g., CSS), please make sure to use `gradle-intellij-plugin` >=0.4.19 ### Changes in Python Plugin 2020.1 diff --git a/reference_guide/api_changes_list.md b/reference_guide/api_changes_list.md index 919eaefdb..ce427b913 100644 --- a/reference_guide/api_changes_list.md +++ b/reference_guide/api_changes_list.md @@ -6,13 +6,11 @@ title: Incompatible Changes in IntelliJ Platform and Plugins API -IntelliJ API may be occasionally changed between releases, leading to incompatibilities of existing plugins with newer IDE builds. +IntelliJ API may be occasionally changed between releases, leading to existing plugins' incompatibilities with newer IDE builds. ## Verifying Compatibility @@ -77,19 +75,19 @@ Compatibility with newer IDEs can easily be verified for plugins hosted on the [ For local verification or non-public plugins, [intellij-plugin-verifier](https://github.com/JetBrains/intellij-plugin-verifier) can be used standalone as well. Integration in [Gradle build](/tutorials/build_system.md) is currently possible via some additional scripts, please see [this issue](https://github.com/JetBrains/gradle-intellij-plugin/issues/385) for details. -If your plugin is hosted on GitHub, it is also readily made available via these GitHub Actions: +If your plugin is hosted on GitHub, it is also readily available via these GitHub Actions: - [IntelliJ Platform Plugin Verifier](https://github.com/marketplace/actions/intellij-platform-plugin-verifier) -- [IntelliJ Plugin Verifier](https://github.com/marketplace/actions/intellij-plugin-verifier) - -### IDE Support +- [IntelliJ Plugin Verifier](https://github.com/marketplace/actions/intellij-plugin-verifier) + +### IDE Support Consider using the following IDE inspections to get additional alerts about code that uses unstable API features: - JVM languages \| Unstable API Usage - JVM languages \| Unstable type is used in signature - - -## Known Breaking Changes - -The following pages list the breaking changes in IDE/plugin releases with required/recommended steps to take by plugin authors. + + +## Known Breaking Changes + +The following pages list the breaking changes in IDE/plugin releases with required/recommended steps to take by plugin authors. * [**Changes in 2020.***](api_changes/api_changes_list_2020.md) * [**Changes in 2019.***](api_changes/api_changes_list_2019.md) diff --git a/reference_guide/api_notable/api_notable.md b/reference_guide/api_notable/api_notable.md index 14ea56bcc..4168658e7 100644 --- a/reference_guide/api_notable/api_notable.md +++ b/reference_guide/api_notable/api_notable.md @@ -5,8 +5,8 @@ title: Notable Changes and Features in IntelliJ Platform and Plugins API The following pages list notable changes and new features in IDE releases. -Plugin authors are encouraged to verify their compatible releases take advantage of the latest API additions. - +Plugin authors are encouraged to verify their compatible releases take advantage of the latest API additions. + * [**Changes in 2020.***](api_notable_list_2020.md) * [**Changes in 2019.***](api_notable_list_2019.md) * [**Changes in 2018.***](api_notable_list_2018.md) diff --git a/reference_guide/api_notable/api_notable_list_2018.md b/reference_guide/api_notable/api_notable_list_2018.md index 5f20bb6e9..30b9039fa 100644 --- a/reference_guide/api_notable/api_notable_list_2018.md +++ b/reference_guide/api_notable/api_notable_list_2018.md @@ -3,7 +3,7 @@ title: Notable Changes in IntelliJ Platform and Plugins API 2018.* --- -## 2018.3 +## 2018.3 ### Notable Changes in IntelliJ Platform 2018.3 @@ -11,17 +11,17 @@ ASM Library 7.0 : Updated to 7.0 [Issue](https://youtrack.jetbrains.com/issue/IDEA-191331). Extendable Registry keys -: Plugins can contribute new keys to _Registry_ dialog via EP `com.intellij.registryKey`. [Issue](https://youtrack.jetbrains.com/issue/IDEA-177378) +: Plugins can contribute new keys to _Registry_ dialog via EP `com.intellij.registryKey`. [Issue](https://youtrack.jetbrains.com/issue/IDEA-177378) Editor: content between text lines : Ability to add arbitrary content (preview, debugger information, etc.). [Issue](https://youtrack.jetbrains.com/issue/IDEA-183815) -## 2018.2 +## 2018.2 ### Notable Changes in IntelliJ Platform 2018.2 _Run Anything_ (**Double CTRL**) -: Allows executing predefined activities using a popup with smart completion, e.g. [Gradle Tasks](https://www.jetbrains.com/help/idea/gradle.html#gradle_tasks), executing Run Configurations, ... see [`RunAnythingProvider`](upsource:///platform/lang-impl/src/com/intellij/ide/actions/runAnything/activity/RunAnythingProvider.java) +: Allows executing predefined activities using a popup with smart completion, e.g., [Gradle Tasks](https://www.jetbrains.com/help/idea/gradle.html#gradle_tasks), executing Run Configurations, ... see [`RunAnythingProvider`](upsource:///platform/lang-impl/src/com/intellij/ide/actions/runAnything/activity/RunAnythingProvider.java) JPS: Report exception in IDE -: Ability to report exceptions from build process. [Issue](https://youtrack.jetbrains.com/issue/IDEA-187115) +: Ability to report exceptions from the build process. [Issue](https://youtrack.jetbrains.com/issue/IDEA-187115) diff --git a/reference_guide/api_notable/api_notable_list_2019.md b/reference_guide/api_notable/api_notable_list_2019.md index 948244c34..187fd51e0 100644 --- a/reference_guide/api_notable/api_notable_list_2019.md +++ b/reference_guide/api_notable/api_notable_list_2019.md @@ -3,36 +3,36 @@ title: Notable Changes in IntelliJ Platform and Plugins API 2019.* --- -## 2019.3 +## 2019.3 ### Notable Changes in IntelliJ Platform 2019.3 `PlatformTestCase` renamed to `HeavyPlatformTestCase` : Now reflects its "heavy test" characteristics (see [Light and Heavy Tests](/basics/testing_plugins/light_and_heavy_tests.md)). - + Support for transitive optional plugin dependencies -: Optional `plugin.xml` configuration files can now specify ``. [Issue](https://youtrack.jetbrains.com/issue/IDEA-209769) +: Optional `plugin.xml` configuration files can now specify ``. [Issue](https://youtrack.jetbrains.com/issue/IDEA-209769) Theme/Keymap plugins do not require restart : (Un)Installing or enabling/disabling [Theme](/reference_guide/ui_themes/themes_intro.md) or [Keymap](https://plugins.jetbrains.com/search?tags=Keymap) plugins doesn't require an IDE restart anymore. - + Run task once (per project) -: Use `com.intellij.ide.util.RunOnceUtil` to run a task exactly once for application or per project. - +: Use `com.intellij.ide.util.RunOnceUtil` to run a task exactly once for application or per project. + Symbol completion in plain text editor (VCS Commit Message) -: Contribute symbol names (classes, methods, ..) via `com.intellij.completion.plainTextSymbol` extension point (`com.intellij.codeInsight.completion.PlainTextSymbolCompletionContributor`). - +: Contribute symbol names (classes, methods, ..) via `com.intellij.completion.plainTextSymbol` extension point (`com.intellij.codeInsight.completion.PlainTextSymbolCompletionContributor`). + User-customizable date/time formatting -: Use `com.intellij.util.text.JBDateFormat#getFormatter()` to use configured format from `Settings | Appearance & Behavior | System Settings | Date Formats`. - +: Use `com.intellij.util.text.JBDateFormat#getFormatter()` to use configured format from `Settings | Appearance & Behavior | System Settings | Date Formats`. + ### Notable Changes in IntelliJ IDEA 2019.3 Unbundled plugins -: Several plugins (Heroku integration, RubyMotion support, Java Applets Support) for no longer actively maintained technology have been moved to a [separate repository](https://github.com/JetBrains/intellij-obsolete-plugins/). +: Several plugins (Heroku integration, RubyMotion support, Java Applets Support) for no longer actively maintained technology have been moved to a [separate repository](https://github.com/JetBrains/intellij-obsolete-plugins/). If your plugin depends on them, users will need to install them from the [JetBrains Plugins Repository](https://plugins.jetbrains.com). - - -## 2019.2 + + +## 2019.2 ### Notable Changes in IntelliJ Platform 2019.2 @@ -40,13 +40,13 @@ Quickfixes for file-level notifications : Consistent with other quickfixes, the menu now shows names of fixes, not names of problems themselves. [Issue](https://youtrack.jetbrains.com/issue/IDEA-216731) Create HTML representation of code -: Use `com.intellij.openapi.editor.richcopy.HtmlSyntaxInfoUtil` to create Lexer-based highlighted code samples, e.g. for usage in documentation. +: Use `com.intellij.openapi.editor.richcopy.HtmlSyntaxInfoUtil` to create Lexer-based highlighted code samples, e.g. for usage in documentation. View \| Appearance \| Description in Tree Views : Toggles showing additional details in UI (e.g. modification timestamp in Project View) see `UISettings.getShowInplaceComments()`. New API for Editor Inlay Hints -: Allows a variety of presentations (incl. custom painting), mouse event handling and exposing settings in _Editor \| Inlay Hints_. See `com.intellij.codeInsight.hints.InlayHintsProvider`. +: Allows a variety of presentations (incl. custom painting), mouse event handling, and exposing settings in _Editor \| Inlay Hints_. See `com.intellij.codeInsight.hints.InlayHintsProvider`. `com.intellij.openapi.vfs.AsyncFileListener` : A non-blocking variant for `com.intellij.openapi.vfs.newvfs.BulkFileListener`. @@ -64,7 +64,7 @@ New API for Editor Inlay Hints : When registering file type via file extension, pattern or exact file name matching, use extension point `com.intellij.fileType` instead (see [Sample](/tutorials/custom_language_support/language_and_filetype.md#b-register-file-type-20192-or-later)). `@org.jetbrains.annotations.ApiStatus.NonExtendable` -: Indicates that the annotated API class, interface or method must not be extended, implemented or overridden by external plugins but can be only obtained or instantiated (for classes and interfaces), or called (for methods). +: Indicates that the annotated API class, interface, or method must not get extended, implemented, or overridden by external plugins but can only be obtained or instantiated for classes and interfaces, or called for methods. `@org.jetbrains.annotations.ApiStatus.OverrideOnly` : Indicates that the annotated method is part of SPI (Service Provider Interface), which is intended to be only implemented or overridden but never called by external plugins. @@ -73,34 +73,34 @@ New API for Editor Inlay Hints : Defaults to thread-safe to prevent problems with clients using unsynchronized collections. `com.intellij.openapi.projectRoots.SdkType#getInvalidHomeMessage` -: Returns dedicated message when invalid SDK path was chosen (e.g., JRE instead of JDK). +: Returns dedicated message when invalid SDK path was chosen (e.g., JRE instead of JDK). ### Notable Changes in IntelliJ IDEA 2019.2 -Java functionality extracted as plugin -: If your plugin depends on Java, it must be specified now, please see [blog post](https://blog.jetbrains.com/platform/2019/06/java-functionality-extracted-as-a-plugin/) for details. +Java functionality extracted as a plugin +: If your plugin depends on Java, it must be specified now; please see [blog post](https://blog.jetbrains.com/platform/2019/06/java-functionality-extracted-as-a-plugin/) for details. Unbundled plugins : Several plugins (J2ME, JsTestDriver, Struts 1.x) for no longer actively maintained technology have been moved to a [separate repository](https://github.com/JetBrains/intellij-obsolete-plugins/). If your plugin depends on them, users will need to install them from the [JetBrains Plugins Repository](https://plugins.jetbrains.com). -## 2019.1 +## 2019.1 ### Notable Changes in IntelliJ Platform 2019.1 `com.intellij.testFramework.InspectionTestCase` changed to light test -: Use dedicated `ProjectDescriptor` or rollback project setup changes in `tearDown()` (see [Light and Heavy Tests](/basics/testing_plugins/light_and_heavy_tests.md)). +: Use dedicated `ProjectDescriptor` or rollback project setup changes in `tearDown()` (see [Light and Heavy Tests](/basics/testing_plugins/light_and_heavy_tests.md)). `@org.jetbrains.annotations.ApiStatus.AvailableSince` -: External annotations for IntelliJ Platform are generated and attached to plugin projects automatically (replacing `@since` Javadoc). +: External annotations for the IntelliJ Platform are generated and attached to plugin projects automatically (replacing `@since` Javadoc). `@org.jetbrains.annotations.ApiStatus.ScheduledForRemoval` -: External annotations for IntelliJ Platform are generated and attached to plugin projects automatically. This allows highlighting of API which has been removed in newer platform versions. +: External annotations for the IntelliJ Platform are generated and attached to plugin projects automatically. This allows highlighting of API, which has been removed in newer platform versions. `@org.jetbrains.annotations.ApiStatus.Internal` -: Indicates that the annotated element must not be considered as a public API. Do not use outside of IntelliJ Platform. [Issue](https://youtrack.jetbrains.com/issue/IDEA-211175) +: Indicates that the annotated element must not be considered as a public API. Do not use outside of the IntelliJ Platform. [Issue](https://youtrack.jetbrains.com/issue/IDEA-211175) `PsiReferenceProvider` assert underlying element : Assert references are created for the given underlying `PsiElement`. [Issue](https://youtrack.jetbrains.com/issue/IDEA-203954) diff --git a/reference_guide/api_notable/api_notable_list_2020.md b/reference_guide/api_notable/api_notable_list_2020.md index 8d090e6e0..0495daf20 100644 --- a/reference_guide/api_notable/api_notable_list_2020.md +++ b/reference_guide/api_notable/api_notable_list_2020.md @@ -59,7 +59,7 @@ ASM Library 8.0.1 : Updated from 7.0.1. Validating Lexer for editor highlighting -: Lexer is wrapped using `ValidatingLexerWrapper` to verify it generates continuous sequence of tokens and doesn't stall during iteration. +: Lexer is wrapped using `ValidatingLexerWrapper` to verify it generates a continuous sequence of tokens and doesn't stall during iteration. ## 2020.1 @@ -75,7 +75,7 @@ Dynamic Plugins : Please see `RecursionManager.CachingPreventedException` Javadoc and [this issue](https://youtrack.jetbrains.com/issue/IDEA-228809) for details. `ResolveCache` using `IdempotenceChecker` in tests -: Reports when the same reference resolves to non-equivalent results in different threads, see [`IdempotenceChecker`](upsource:///platform/core-impl/src/com/intellij/util/IdempotenceChecker.java). +: Reports when the same reference resolves non-equivalent results in different threads, see [`IdempotenceChecker`](upsource:///platform/core-impl/src/com/intellij/util/IdempotenceChecker.java). Refactoring dialog: builtin "Open in editor" option : Set `addOpenInEditorCheckbox` constructor parameter to enable it in custom `RefactoringDialog` implementation. diff --git a/reference_guide/color_scheme_management.md b/reference_guide/color_scheme_management.md index e8c459ec2..2c15b90b5 100644 --- a/reference_guide/color_scheme_management.md +++ b/reference_guide/color_scheme_management.md @@ -5,12 +5,13 @@ title: Color Scheme Management ## Preface -Color scheme management in IntelliJ IDEA 12.1 was changed to ease the work of scheme designers and make schemes look equally well for different programming languages even if not designed specifically for these languages. +Color scheme management in IntelliJ IDEA 12.1 was changed to ease scheme designers' work and make schemes look equally well for different programming languages even if not designed specifically for these languages. Previously language plug-ins were using fixed default colors incompatible, for example, with dark schemes. -The new implementation allows to specify a dependency on a set of standard text attributes which are linked to a scheme but not to any specific language. Language-specific attributes still can be set by a scheme designer if needed but it's optional. +The new implementation allows specifying a dependency on a set of standard text attributes linked to a scheme but not to any specific language. +Language-specific attributes still can be set by a scheme designer if needed, but it's optional. New color schemes have got a new `.icls` (Idea CoLor Scheme) extension to avoid confusion about compatibility problems with older platform versions: -if only standard attributes are set, they will not be used by the version prior to 12.1 and this will result in different highlighting colors. +if only standard attributes are set, they will not be used by the version before 12.1, resulting in different highlighting colors. ## Plug-in Developers @@ -19,28 +20,28 @@ if only standard attributes are set, they will not be used by the version prior The easiest and the best way to specify highlighting text attributes is to specify a dependency on one of standard keys defined in [`DefaultLanguageHighlighterColors`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/DefaultLanguageHighlighterColors.java): ```java -static final TextAttributesKey MY_KEYWORD = +static final TextAttributesKey MY_KEYWORD = TextAttributesKey.createTextAttributesKey("MY_KEYWORD", DefaultLanguageHighlighterColors.KEYWORD); ``` -Color scheme manager will search first for text attributes specified by `MY_KEYWORD` key. -If those are not defined explicitly or if all the attributes are empty (undefined), it will search them using `DEFAULT_KEYWORD` key. -If neither are defined, it will further fall back to a default scheme. +The color scheme manager will search first for text attributes specified by the `MY_KEYWORD` key. +If those are not defined explicitly or if all the attributes are empty (undefined), it will search them using the `DEFAULT_KEYWORD` key. +If neither is defined, it will further fall back to a default scheme. Text attribute keys can be chained, for example you can define another key as: ```java -static final TextAttributesKey MY_PREDEFINED_SYMBOL = +static final TextAttributesKey MY_PREDEFINED_SYMBOL = TextAttributesKey.createTextAttributesKey("MY_PREDEFINED_SYMBOL", MY_KEYWORD); ``` -The rule is the same: if text attributes can not be found by `MY_PREDEFINED_SYMBOL` key or are empty, the color scheme manager will search for `MY_KEYWORD` and if not found (empty) will further look for `DEFAULT_KEYWORD`. +The rule is the same: if text attributes can not be found by the `MY_PREDEFINED_SYMBOL` key or are empty, the color scheme manager will search for `MY_KEYWORD` and if not found (empty) will further look for `DEFAULT_KEYWORD`. -> **NOTE** A use of fixed default attributes is _strongly discouraged_. +> **NOTE** A use of fixed default attributes is _strongly discouraged_. -If you are not sure which base key to use, it's better to pick the most generic one, for example, `DefaultLanguageHighlighterColors.IDENTIFIER`. -Remember that using fixed default attributes *will force* a scheme designer to set up a color for this element explicitly. -Otherwise its default colors may visually conflict with a color scheme. +If you are unsure which base key to use, it's better to pick the most generic one, for example, `DefaultLanguageHighlighterColors.IDENTIFIER`. +Remember that using fixed default attributes *will force* a scheme designer to explicitly set up a color for this element. +Otherwise, its default colors may visually conflict with a color scheme. If the scheme designer doesn't have a language plug-in, he will not be able to fix this at all. ### Providing Attributes for Specific Schemes @@ -58,7 +59,7 @@ This can be done in `plugin.xml` by adding an `com.intellij.additionalTextAttrib It tells the IDE that the file `MyLangDefault.xml` must be searched in resources under `colorSchemes`. Note that the path should *not* start with a backslash and its fully qualified name (in our case `colorSchemes/MyLangDefault.xml`) *MUST BE UNIQUE* to avoid naming collisions between different providers. -Thus adding a language prefix, for example "MyLang", is highly recommended. +Thus adding a language prefix, for example, "MyLang", is highly recommended. The file itself is an extract from a color scheme with required attributes, for example: @@ -80,33 +81,28 @@ The file itself is an extract from a color scheme with required attributes, for ``` -*Note:* When the scheme is copied via "Save as...", all its attributes including the ones defined in the extension will be copied to the new scheme as well. -A scheme designer may need to check that these copied attributes do not conflict with his/her color scheme although in this case the plug-in is installed and it should not cause any problems. -Anyway, try to stick with a simple key dependency if possible (note that it works well for "Darcula" too), provide explicit attributes only if really necessary. +*Note:* When the scheme is copied via "Save as..." all its attributes, including the ones defined in the extension, will be copied to the new scheme. +A scheme designer may need to check that these copied attributes do not conflict with his/her color scheme, although in this case the plug-in is installed, and it should not cause any problems. +Anyway, try to stick with a simple key dependency if possible (note that it works well for "Darcula") and provide explicit attributes only if necessary. ## Scheme Designers ### A Typical Workflow for a New Scheme Creation -* Choose a scheme which will be used as a base, for example "Default" +* Choose a scheme which will be used as a base, for example, "Default" +* Click "Save As.." and give a name for the new scheme +* First set attributes in *General* section and proceed with *Language Defaults* +* Check all the languages and adjust language-specific text attributes if necessary. + In most cases this may not be needed, but two cases may require an extra action: -* Click "Save As.." and give a name for the new scheme - -* First set attributes in *General* section and proceed with *Language Defaults* - -* Check all the languages and adjust language-specific text attributes if necessary. -In most cases this may not be needed but there are two cases which may require an extra action: - - * There is an obsolete plug-in which does not use the new color scheme management API and therefore does not utilize the attributes set in "Language Defaults". - Ideally a report must be created for the language plug-in so that its author will fix it eventually. - - * A plug-in intentionally sets some default colors and, if the scheme was created from a default one, the colors are copied to the newly created scheme. - This can be fixed either by resetting all the attributes to restore the inheritance from Language Defaults (see below) or by setting other colors suitable for the scheme. - The first way is preferable since it will require less effort to change the color scheme later. + * There is an obsolete plug-in which does not use the new color scheme management API and therefore does not utilize the attributes set in "Language Defaults". + Ideally, a report must be created for the language plug-in so that its author will fix it eventually. + * A plug-in intentionally sets some default colors and, if the scheme was created from a default one, the colors are copied to the newly created scheme. + This can be fixed either by resetting all the attributes to restore the inheritance from Language Defaults (see below) or by setting other colors suitable for the scheme. + The first way is preferable since it will require less effort to change the color scheme later. ### Text Attributes Inheritance -For many language text attributes which do not have any values there will be a line indicating that the attributes are inherited from a certain section/attributes, for example: "Keyword (Language Defaults)". -If an element has *any* attributes set, only these attributes are used, all attributes from the base element are ignored. -To *restore* the inheritance uncheck all the boxes and click *Apply*. - +For many language text attributes that do not have any values, there will be a line indicating that the attributes are inherited from a specific section/attributes, such as "Keyword (Language Defaults)". +If an element has *any* attributes set, only these attributes are used. All attributes from the base element are ignored. +To *restore* the inheritance, unchecks all the boxes, and click *Apply*. diff --git a/reference_guide/custom_language_support.md b/reference_guide/custom_language_support.md index 0725a2a09..072f594c0 100644 --- a/reference_guide/custom_language_support.md +++ b/reference_guide/custom_language_support.md @@ -5,17 +5,15 @@ title: Custom Language Support *IntelliJ Platform* is a powerful platform for building development tools targeting *any* language. Most of the IDE features consist of language-independent (provided by the platform) and language-specific parts. -Supporting a particular feature for a new language can be achieved with a small amount of effort: +Supporting a particular feature for a new language can be achieved with a small amount of effort: a plugin must implement only the language-specific part. This part of the documentation explains the main concepts of the *Language API* and guides you through the sequence of steps that are usually required to develop a custom language plugin. -You can obtain additional information about the *Language API* from the JavaDoc comments for the *Language API* classes and from the source code of the Properties language support, which is part of the -[IntelliJ IDEA Community Edition](https://github.com/JetBrains/intellij-community) -source code. - +You can obtain additional information about the *Language API* from the JavaDoc comments for the *Language API* classes and from the Properties language support source code, which is part of the [IntelliJ IDEA Community Edition](https://github.com/JetBrains/intellij-community) source code. If you prefer a full example to the detailed descriptions offered in this section, please check out a step-by-step tutorial on how to create custom language support for _Simple Language_: -[Custom Language Support Tutorial](/tutorials/custom_language_support_tutorial.md). Corresponding steps from the tutorial are linked under "Examples" section on each page of this reference. +[Custom Language Support Tutorial](/tutorials/custom_language_support_tutorial.md). +Corresponding steps from the tutorial are linked under the "Examples" section on each page of this reference. The webinar [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/) offers an excellent introduction as well. @@ -40,4 +38,3 @@ Providing custom language support includes the following major steps: * [Go to Class and Go to Symbol](/reference_guide/custom_language_support/go_to_class_and_go_to_symbol.md) * [Documentation](/reference_guide/custom_language_support/documentation.md) * [Additional Minor Features](/reference_guide/custom_language_support/additional_minor_features.md) - diff --git a/reference_guide/custom_language_support/additional_minor_features.md b/reference_guide/custom_language_support/additional_minor_features.md index feb0cf293..39f783946 100644 --- a/reference_guide/custom_language_support/additional_minor_features.md +++ b/reference_guide/custom_language_support/additional_minor_features.md @@ -16,35 +16,28 @@ _- Sample 1_ - Sample implementation EP: `com.intellij.lang.braceMatcher` [`PairedBraceMatcher`](upsource:///platform/analysis-api/src/com/intellij/lang/PairedBraceMatcher.java) -Returns an array of brace pairs ( -[`BracePair`](upsource:///platform/analysis-api/src/com/intellij/lang/BracePair.java) -) specifying the characters for the opening and closing braces and the lexer token types for these characters. +Returns an array of brace pairs ([`BracePair`](upsource:///platform/analysis-api/src/com/intellij/lang/BracePair.java)) specifying the characters for the opening and closing braces and the lexer token types for these characters. (In principle, it is possible to return multi-character tokens, like "begin" and "end", as the start and end tokens of a brace pair. -The IDE will match such braces, but the highlighting for such braces will not be fully correct.) +The IDE will match such braces, but the highlighting for such braces will not be entirely correct.) Certain types of braces can be marked as structural. -Structural braces have higher priority than regular braces: they are matched with each other even if there are unmatched braces of other types between them. +Structural braces have higher priority than regular braces: they are matched with each other even if there are unmatched braces of different types between them. An opening non-structural brace is not matched with a closing one if one of them is inside a pair of matched structural braces and another is outside. ### Comment Code EP: `com.intellij.lang.commenter` -[`Commenter`](upsource:///platform/core-api/src/com/intellij/lang/Commenter.java) -Returns the prefix for the line comment, and the prefix and suffix for the block comment, if supported by the language. +[`Commenter`](upsource:///platform/core-api/src/com/intellij/lang/Commenter.java) returns the prefix for the line comment, and the prefix and suffix for the block comment if supported by the language. -- [`Commenter`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesCommenter.java) -for [Properties language plugin](upsource:///plugins/properties/) +- [`Commenter`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesCommenter.java) for [Properties language plugin](upsource:///plugins/properties/) - [Custom Language Support Tutorial: Commenter](/tutorials/custom_language_support/commenter.md) ### Code Folding EP: `com.intellij.lang.foldingBuilder` -[`FoldingBuilder`](upsource:///platform/core-api/src/com/intellij/lang/folding/FoldingBuilder.java) -Returns the list of text ranges that are foldable (as an array of -[`FoldingDescriptor`](upsource:///platform/core-api/src/com/intellij/lang/folding/FoldingDescriptor.java) -objects), the replacement text which is shown for each range when it is folded, and the default state of each folding region (folded or unfolded). +[`FoldingBuilder`](upsource:///platform/core-api/src/com/intellij/lang/folding/FoldingBuilder.java) returns the list of foldable text ranges (as an array of [`FoldingDescriptor`](upsource:///platform/core-api/src/com/intellij/lang/folding/FoldingDescriptor.java) objects), the replacement text which is shown for each range when it is folded, and the default state of each folding region (folded or unfolded). - [Custom Language Support Tutorial: Folding Builder](/tutorials/custom_language_support/folding_builder.md) @@ -52,68 +45,56 @@ objects), the replacement text which is shown for each range when it is folded, ### Join Lines EP: `com.intellij.joinLinesHandler` -[`JoinLinesHandlerDelegate`](upsource:///platform/lang-api/src/com/intellij/codeInsight/editorActions/JoinLinesHandlerDelegate.java) -allows extending support smart/semantic *Edit \| Join Lines* (e.g., String literal split on multiple lines). +[`JoinLinesHandlerDelegate`](upsource:///platform/lang-api/src/com/intellij/codeInsight/editorActions/JoinLinesHandlerDelegate.java) allows extending support smart/semantic *Edit \| Join Lines* (e.g., String literal split on multiple lines). ### Smart Enter EP: `com.intellij.lang.smartEnterProcessor` -[`SmartEnterProcessor`](upsource:///platform/lang-api/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterProcessor.java) -handles *Edit \| Complete Statement* (e.g., autocomplete missing semicolon/parentheses). +[`SmartEnterProcessor`](upsource:///platform/lang-api/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterProcessor.java) handles *Edit \| Complete Statement* (e.g., autocomplete missing semicolon/parentheses). + - ### Naming Suggestions EP: `com.intellij.nameSuggestionProvider` -[`NameSuggestionProvider`](upsource:///platform/lang-api/src/com/intellij/refactoring/rename/NameSuggestionProvider.java). -provides name suggestions for the given element, e.g., for Rename refactoring. +[`NameSuggestionProvider`](upsource:///platform/lang-api/src/com/intellij/refactoring/rename/NameSuggestionProvider.java) provides name suggestions for the given element, e.g., for Rename refactoring. ### Semantic Highlight Usages EP: `com.intellij.highlightUsagesHandlerFactory` -[`HighlightUsagesHandlerFactory`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactory.java) -allows highlighting e.g. Exit Points or Exceptions. +[`HighlightUsagesHandlerFactory`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandlerFactory.java) allows highlighting e.g., Exit Points or Exceptions. ### Parameter Info EP: `com.intellij.codeInsight.parameterInfo` -[`ParameterInfoHandler`](upsource:///platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoHandler.java) -provides support for *View \| Parameter Info*. +[`ParameterInfoHandler`](upsource:///platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoHandler.java) provides support for *View \| Parameter Info*. ### To Do View EP: n/a -[`ParserDefinition.getCommentTokens()`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java) -must return the set of tokens treated as comments to populate *To Do View*. +[`ParserDefinition.getCommentTokens()`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java) must return the set of tokens treated as comments to populate *To Do View*. ### Context Info EP: `com.intellij.declarationRangeHandler` -[`DeclarationRangeHandler`](upsource:///platform/lang-api/src/com/intellij/codeInsight/hint/DeclarationRangeHandler.java) -provides *View \| Context Info* for custom languages with structure view implementation based on a -[`TreeBasedStructureViewBuilder`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/TreeBasedStructureViewBuilder.java). +[`DeclarationRangeHandler`](upsource:///platform/lang-api/src/com/intellij/codeInsight/hint/DeclarationRangeHandler.java) provides *View \| Context Info* for custom languages with structure view implementation based on a [`TreeBasedStructureViewBuilder`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/TreeBasedStructureViewBuilder.java). ### Spellchecking EP: `com.intellij.spellchecker.support` -[`SpellcheckingStrategy`](upsource:///spellchecker/src/com/intellij/spellchecker/tokenizer/SpellcheckingStrategy.java) -provides [`Tokenizer`](upsource:///spellchecker/src/com/intellij/spellchecker/tokenizer/Tokenizer.java) -to use for given `PsiElement` (return `EMPTY_TOKENIZER` for no spellchecking). +[`SpellcheckingStrategy`](upsource:///spellchecker/src/com/intellij/spellchecker/tokenizer/SpellcheckingStrategy.java) provides [`Tokenizer`](upsource:///spellchecker/src/com/intellij/spellchecker/tokenizer/Tokenizer.java) to use for given `PsiElement` (return `EMPTY_TOKENIZER` for no spellchecking). ### Reference Injection EP: `com.intellij.referenceInjector` -[`ReferenceInjector`](upsource:///platform/lang-api/src/com/intellij/psi/injection/ReferenceInjector.java) -allows users to inject pre-defined references (e.g., "Encoding", "File Reference") into `PsiLanguageInjectionHost` elements (IntelliLang plugin required). +[`ReferenceInjector`](upsource:///platform/lang-api/src/com/intellij/psi/injection/ReferenceInjector.java) allows users to inject pre-defined references (e.g., "Encoding", "File Reference") into `PsiLanguageInjectionHost` elements (IntelliLang plugin required). ### Color Preview/Chooser EP: `com.intellij.colorProvider` - -[`ElementColorProvider`](upsource:///platform/lang-api/src/com/intellij/openapi/editor/ElementColorProvider.java) -renders gutter icon for element containing color information. + +[`ElementColorProvider`](upsource:///platform/lang-api/src/com/intellij/openapi/editor/ElementColorProvider.java) renders gutter icon for element containing color information. diff --git a/reference_guide/custom_language_support/code_completion.md b/reference_guide/custom_language_support/code_completion.md index 8c4624f71..8a6d61139 100644 --- a/reference_guide/custom_language_support/code_completion.md +++ b/reference_guide/custom_language_support/code_completion.md @@ -3,30 +3,18 @@ title: Code Completion --- -There are two main types of code completion that can be provided by custom language plugins: reference completion and contributor-based completion. +Two main types of code completion can be provided by custom language plugins: reference completion and contributor-based completion. Reference completion is easier to implement, but supports only the basic completion action. -Contributor-based completion provides more features, supports all three completion types (basic, smart and class name) and can be used, for example, to implement keyword completion. +Contributor-based completion provides more features, supports all three completion types (basic, smart, and class name), and can be used, for example, to implement keyword completion. ### Reference Completion -To fill the completion list, the IDE calls -[`PsiReference.getVariants()`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) -either on the reference at the caret location or on a dummy reference that would be placed at the caret. -This method needs to return an array of objects containing either strings, -[`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) -instances or instances of the -[`LookupElement`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/lookup/LookupElement.java) -class (see [Lookup Items](#lookup-items) below). -If a -[`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) -instance is returned in the array, the completion list shows the icon for the element. +To fill the completion list, the IDE calls [`PsiReference.getVariants()`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) either on the reference at the caret location or on a dummy reference that would be placed at the caret. +This method needs to return an array of objects containing either strings, [`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) instances or instances of the [`LookupElement`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/lookup/LookupElement.java) class (see [Lookup Items](#lookup-items) below). +If a [`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) instance is returned in the array, the completion list shows the icon for the element. -The most common way to implement `getVariants()` is to use the same function for walking up the tree as in -[`PsiReference.resolve()`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java), -and a different implementation of -[`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) -which collects all declarations passed to its `processDeclarations()` method and returns them as an array for filling the completion list. +The most common way to implement `getVariants()` is to use the same function for walking up the tree as in [`PsiReference.resolve()`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java), and a different implementation of [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) which collects all declarations passed to its `processDeclarations()` method and returns them as an array for filling the completion list. #### Symbol Reference Completion @@ -37,40 +25,29 @@ To provide completion variants by a `PsiSymbolReference` implement ### Contributor-Based Completion -Implementing the -[`CompletionContributor`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/completion/CompletionContributor.java) -interface gives you the greatest control over the operation of code completion for your language. +Implementing the [`CompletionContributor`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/completion/CompletionContributor.java) interface gives you the greatest control over the operation of code completion for your language. > **NOTE** Note that the JavaDoc of that class contains a detailed FAQ for implementing code completion. -The core scenario of using -[`CompletionContributor`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/completion/CompletionContributor.java) -consists of calling the `extend()` method and passing in the *pattern* specifying the context in which this completion variant is applicable, as well as a *completion provider* which generates the items to show in the completion list. +The core scenario of using [`CompletionContributor`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/completion/CompletionContributor.java) consists of calling the `extend()` method and passing in the *pattern* specifying the context in which this completion variant is applicable, as well as a *completion provider* which generates the items to show in the completion list. -Keep in mind that the pattern is checked against the leaf PSI element. If you -want to match a composite element, use `withParent()` or `withSuperParent()` -methods. +Keep in mind that the pattern is checked against the leaf PSI element. +If you want to match a composite element, use `withParent()` or `withSuperParent()` methods. **Examples**: -- [`CompletionContributor`](https://github.com/JetBrains/intellij-plugins/blob/master/osmorc/src/org/osmorc/manifest/completion/OsgiManifestCompletionContributor.java) -for completing keywords in MANIFEST.MF files. +- [`CompletionContributor`](https://github.com/JetBrains/intellij-plugins/blob/master/osmorc/src/org/osmorc/manifest/completion/OsgiManifestCompletionContributor.java) for completing keywords in MANIFEST.MF files. - [Custom Language Support Tutorial: Completion Contributor](/tutorials/custom_language_support/completion_contributor.md) - ### Lookup Items -Items shown in the completion list are represented by instances of the -[`LookupElement`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/lookup/LookupElement.java) -interface. -These instances are normally created through the -[`LookupElementBuilder`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java) -class. +Items shown in the completion list are represented by instances of the [`LookupElement`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/lookup/LookupElement.java) interface. +These instances are typically created through the [`LookupElementBuilder`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java) class. For every lookup element, you can specify the following attributes: * Text. Shown left-aligned. -* Tail text. Shown next to the main item text, is not used for prefix matching, and can be used, for example, to show the parameter list of the method. +* Tail text. Shown next to the main item text, is not used for prefix matching, and can be used, for example, to show the parameter list of the method. * Type text. Shown right-aligned in the lookup list and can be used to show the return type or containing class of a method, for example. * Icon * Text attributes. Bold, Strikeout, etc. -* Insert handler. The insert handler is a callback which is called when the item is selected, and can be used to perform additional modifications of the text (for example, to put in the parentheses for a method call) +* Insert handler. The insert handler is a callback which is called when the item is selected and can be used to perform additional modifications of the text (for example, to put in the parentheses for a method call) diff --git a/reference_guide/custom_language_support/code_formatting.md b/reference_guide/custom_language_support/code_formatting.md index 1416314cd..0334a5890 100644 --- a/reference_guide/custom_language_support/code_formatting.md +++ b/reference_guide/custom_language_support/code_formatting.md @@ -4,7 +4,8 @@ title: Code Formatter The IntelliJ Platform includes a powerful framework for implementing custom language formatters. -In this framework, the plugin specifies the *constraints* on the spacing between different syntax elements, and the formatting engine, provided by the IDE, calculates the smallest number of whitespace modifications that need to be performed on the file to make it match the constraints. +In this framework, the plugin specifies the *constraints* on the spacing between different syntax elements. +The formatting engine, provided by the IDE, calculates the smallest number of whitespace modifications that need to be performed on the file to make it match the constraints. The process of formatting a file or a file fragment consists of the following main steps: @@ -16,44 +17,41 @@ The process of formatting a file or a file fragment consists of the following ma * The formatting model is requested to build the structure of the file as applies to formatting, as a tree of _blocks_ ( [`Block`](upsource:///platform/lang-api/src/com/intellij/formatting/Block.java) - ) with associated indent, wrap, alignment and spacing settings. + ) with an associated indent, wrap, alignment, and spacing settings. -* The formatting engine calculates the sequence of whitespace characters (spaces, tabs and/or line breaks) that needs to be placed at every block boundary, based on the formatting model provided by the plugin. +* The formatting engine calculates the sequence of whitespace characters (spaces, tabs, and/or line breaks) that needs to be placed at every block boundary, based on the plugin's formatting model. * The formatting model is requested to insert the calculated whitespace characters at necessary positions in the file. -The structure of blocks is usually built in such a way that it mirrors the PSI structure of the file - for example, in Java code, the top-level formatting block covers the entire file, its children cover individual classes in the file, blocks on the next level cover methods inside classes, and so on. The formatter modifies only the characters between blocks, and the tree of blocks must be built in such a way that the bottom-level blocks cover all non-whitespace characters in the file: otherwise the characters between blocks may be deleted by the formatter. +The structure of blocks is usually built so that it mirrors the PSI structure of the file - for example, in Java code, the top-level formatting block covers the entire file. +Its children cover individual classes in the file, blocks on the next level cover methods inside classes, etc. +The formatter modifies only the characters between blocks, and the tree of blocks must be built so that the bottom-level blocks cover all non-whitespace characters in the file. +Otherwise, the characters between blocks may be deleted by the formatter. -If the formatting operation does not affect the entire file (for example, if the formatter is called to format the pasted block of text), a complete tree of blocks is not built - rather, only blocks for the text range covered by the formatting operation and their parents are built. +If the formatting operation does not affect the entire file (for example, if the formatter is called to format the pasted block of text), a complete tree of blocks is not built. +Rather, only blocks for the text range covered by the formatting operation and their parents are built. For every block, the plugin specifies the following properties: -* The _spacing_ ( - [`Spacing`](upsource:///platform/lang-api/src/com/intellij/formatting/Spacing.java) - ) specifies what spaces or line breaks are inserted between the specified children of the block. - The spacing object specifies the minimum and maximum number of spaces that must be placed between the specified child blocks, the minimum number of line breaks to place there, and whether the existing line breaks and blank lines should be preserved. +* The _spacing_ ([`Spacing`](upsource:///platform/lang-api/src/com/intellij/formatting/Spacing.java)) specifies what spaces or line breaks are inserted between the specified children of the block. + The spacing object specifies the minimum and maximum number of spaces that must be placed between the specified child blocks, the minimum number of line breaks to put there, and whether the existing line breaks and blank lines should be preserved. The formatting model can also specify that the spacing between the specified blocks may not be modified by the formatter. * The _indent_ specifies how the block is indented relative to its parent block. There are different modes of indenting defined by factory methods in the Indent class. - The most commonly used are the none indent (which means the child block is not indented), the regular indent (the child block is indented by the number of spaces specified in the **Project Code Style \| General \| Indent** setting) and the continuation indent (based on **Project Code Style \| General \| Continuation Indent** setting). - If the formatting model does not specify an indent, the "continuation without first" mode is used, which means that the first block in a sequence of blocks with that type is not indented and the following blocks are indented with a continuation indent. + The most commonly used are the none indent (which means the child block is not indented), the regular indent (the child block is indented by the number of spaces specified in the **Project Code Style \| General \| Indent** setting), and the continuation indent (based on **Project Code Style \| General \| Continuation Indent** setting). + If the formatting model does not specify an indent, the "continuation without first" mode is used. + This default means that the first block in a sequence of blocks with that type is not indented, and the following blocks are indented with a continuation indent. -* The _wrap_ ( - [`Wrap`](upsource:///platform/lang-api/src/com/intellij/formatting/Wrap.java) - ) specifies whether the content of the block is wrapped to the next line. +* The _wrap_ ([`Wrap`](upsource:///platform/lang-api/src/com/intellij/formatting/Wrap.java)) specifies whether the content of the block is wrapped to the next line. Wrapping is performed by inserting a line break before the block content. The plugin can specify that a particular block is never wrapped, always wrapped, or wrapped only if it exceeds the right margin. -* The _alignment_ ( - [`Alignment`](upsource:///platform/lang-api/src/com/intellij/formatting/Alignment.java) - ) specifies which blocks should be aligned with each other. - If two blocks with the alignment property set to the same object instance are placed in different lines, and if the second block is the first non-whitespace block in its line, the formatter inserts white spaces before the second block so that it starts from the same column as the first one. +* The _alignment_ ([`Alignment`](upsource:///platform/lang-api/src/com/intellij/formatting/Alignment.java)) specifies which blocks should be aligned with each other. + If two blocks with the alignment property set to the same object instance are placed in different lines, and if the second block is the first non-whitespace block in its line, the formatter inserts white spaces before the second block, so that it starts from the same column as the first one. -For each of these properties, a number of special use settings exists, which are described in the JavaDoc comments for the respective classes. -See also -[`SpacingBuilder`](upsource:///platform/lang-api/src/com/intellij/formatting/SpacingBuilder.java) -which aids in building rule-based configuration. +For each of these properties, several particular use settings exist, described in the JavaDoc comments for the respective classes. +See also [`SpacingBuilder`](upsource:///platform/lang-api/src/com/intellij/formatting/SpacingBuilder.java), which aids in building rule-based configuration. An important special case in using the formatter is the smart indent performed when the user presses the `Enter` key in a source code file. To determine the indent for the new line, the formatter engine calls the method `getChildAttributes()` on either the block immediately before the caret or the parent of that block, depending on the return value of the `isIncomplete()` method for the block before the caret. @@ -67,9 +65,7 @@ Code formatting can be suppressed per region via [special comments](https://yout ### Code Style Settings -To specify the default indent size for the language provided by your plugin, and to allow the user to configure the tab size and indent size you need to implement the -[`FileTypeIndentOptionsProvider`](upsource:///platform/lang-api/src/com/intellij/psi/codeStyle/FileTypeIndentOptionsProvider.java) -interface and to register the implementation in the `com.intellij.fileTypeIndentOptionsProvider` extension point. +To specify the default indent size for the language provided by your plugin, and to allow the user to configure the tab size and indent size, you need to implement the [`FileTypeIndentOptionsProvider`](upsource:///platform/lang-api/src/com/intellij/psi/codeStyle/FileTypeIndentOptionsProvider.java) interface and to register the implementation in the `com.intellij.fileTypeIndentOptionsProvider` extension point. The return value of `createIndentOptions()` determines the default indent size. **Example**: @@ -80,6 +76,4 @@ The return value of `createIndentOptions()` determines the default indent size. **New in IntelliJ IDEA 12:** Allows custom languages to provide user-configurable arrangement/grouping rules for element types supported by language plugin. Rules can be refined via modifiers and name, ordering can be applied additionally. -Please see -[`Rearranger`](upsource:///platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java) -and related for JavaDoc. +Please see [`Rearranger`](upsource:///platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java) and related for JavaDoc. diff --git a/reference_guide/custom_language_support/code_inspections_and_intentions.md b/reference_guide/custom_language_support/code_inspections_and_intentions.md index 33ae592ac..00c433cd7 100644 --- a/reference_guide/custom_language_support/code_inspections_and_intentions.md +++ b/reference_guide/custom_language_support/code_inspections_and_intentions.md @@ -5,23 +5,16 @@ title: Code Inspections and Intentions ### Inspections -The code inspections for custom languages use the same API as all other code inspections, based on the -[`LocalInspectionTool`](upsource:///platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java) -class. +The code inspections for custom languages use the same API as all other code inspections, based on the [`LocalInspectionTool`](upsource:///platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java) class. -The functionality of -[`LocalInspectionTool`](upsource:///platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java) -partially duplicates that of -[Annotator](syntax_highlighting_and_error_highlighting.md#annotator). +The functionality of [`LocalInspectionTool`](upsource:///platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java) partially duplicates that of [Annotator](syntax_highlighting_and_error_highlighting.md#annotator). The main differences are: - supports batch analysis of code (through the **Analyze \| Inspect Code...** action) -- the possibility to turn off the inspection (globally or by suppressing them on various levels) +- the possibility to turn off the inspection (globally or by suppressing them on various levels) - ability to configure the inspection options. -If none of that is required and the analysis only needs to run in the active editor, -[Annotator](syntax_highlighting_and_error_highlighting.md#annotator) -provides better performance (because of its support for incremental analysis) and more flexibility for highlighting errors. +If none of that is required and the analysis only needs to run in the active editor, [Annotator](syntax_highlighting_and_error_highlighting.md#annotator) provides better performance (because it supports incremental analysis) and more flexibility for highlighting errors. **Examples**: - [Code Inspections Tutorial](/tutorials/code_inspections.md) @@ -30,10 +23,8 @@ provides better performance (because of its support for incremental analysis) an ### Intentions -The code intentions for custom languages also use the regular API for intentions. -The intention classes need to implement the -[`IntentionAction`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java) -interface and are registered using the `com.intellij.intentionAction` extension point. +The code intentions for custom languages also use the standard API for intentions. +The intention classes need to implement the [`IntentionAction`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java) interface and are registered using the `com.intellij.intentionAction` extension point. **Examples:** - [Code Intentions Tutorial](/tutorials/code_intentions.md) diff --git a/reference_guide/custom_language_support/documentation.md b/reference_guide/custom_language_support/documentation.md index 1d2ef7574..3c5878004 100644 --- a/reference_guide/custom_language_support/documentation.md +++ b/reference_guide/custom_language_support/documentation.md @@ -3,17 +3,12 @@ title: Documentation --- -To provide different kinds of documentation support, the plugin needs to provide an implementation of the -[`DocumentationProvider`](upsource:///platform/analysis-api/src/com/intellij/lang/documentation/DocumentationProvider.java) -interface and register it in the `com.intellij.lang.documentationProvider` extension point. -A standard base class for such implementations is available in the class -[`AbstractDocumentationProvider`](upsource:///platform/analysis-api/src/com/intellij/lang/documentation/AbstractDocumentationProvider.java). +To provide different kinds of documentation support, the plugin needs to provide an implementation of the [`DocumentationProvider`](upsource:///platform/analysis-api/src/com/intellij/lang/documentation/DocumentationProvider.java) interface and register it in the `com.intellij.lang.documentationProvider` extension point. +A standard base class for such implementations is available in the class [`AbstractDocumentationProvider`](upsource:///platform/analysis-api/src/com/intellij/lang/documentation/AbstractDocumentationProvider.java). The `getQuickNavigateInfo()` method returns the text to be displayed when the user holds the mouse over an element with Ctrl pressed. When generating complete documentation via `generateDoc()`, use [`DocumentationMarkup`](upsource:///platform/analysis-api/src/com/intellij/lang/documentation/DocumentationMarkup.java) to layout contents (see JavaDoc for details). **Example**: -[`DocumentationProvider`](upsource:///plugins/properties/src/com/intellij/lang/properties/PropertiesDocumentationProvider.java) -for -[Properties language plugin](upsource:///plugins/properties/) +[`DocumentationProvider`](upsource:///plugins/properties/src/com/intellij/lang/properties/PropertiesDocumentationProvider.java) for [Properties language plugin](upsource:///plugins/properties/) diff --git a/reference_guide/custom_language_support/find_usages.md b/reference_guide/custom_language_support/find_usages.md index 713dbffc0..ae717b810 100644 --- a/reference_guide/custom_language_support/find_usages.md +++ b/reference_guide/custom_language_support/find_usages.md @@ -5,90 +5,37 @@ title: Find Usages The _Find Usages_ action is a multi-step process, and each step of the process requires involvement from the custom language plugin. -The language plugin participates in the Find Usages process by registering an implementation of -[`FindUsagesProvider`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java) -in the `com.intellij.lang.findUsagesProvider` extension point, and through the PSI implementation using -[`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) -and -[`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) -interfaces. +The language plugin participates in the Find Usages process by registering an implementation of [`FindUsagesProvider`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java) in the `com.intellij.lang.findUsagesProvider` extension point, and through the PSI implementation using [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) and [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) interfaces. **Examples**: -- Implementation of -[`FindUsagesProvider`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/findUsages/PropertiesFindUsagesProvider.java) -in -[Properties language plugin](upsource:///plugins/properties/) +- Implementation of [`FindUsagesProvider`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/findUsages/PropertiesFindUsagesProvider.java) in [Properties language plugin](upsource:///plugins/properties/) - [Custom Language Support Tutorial: Find Usages](/tutorials/custom_language_support/find_usages_provider.md) The steps of the _Find Usages_ action are the following: +* Before the _Find Usages_ action can be invoked, the IDE builds an index of words present in every file in the custom language. + Using the [`WordsScanner`](upsource:///platform/indexing-api/src/com/intellij/lang/cacheBuilder/WordsScanner.java) implementation returned from [`FindUsagesProvider.getWordsScanner()`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java), the contents of every file are loaded and passes it to the words scanner, along with the words consumer. + The words scanner breaks the text into words, defines the context for each word (code, comments, or literals), and passes the word to the consumer. + The simplest way to implement the words scanner is to use the [`DefaultWordsScanner`](upsource:///platform/indexing-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java) implementation, passing to it the sets of lexer token types which are treated as identifiers, literals, and comments. + The default words scanner will use the lexer to break the text into tokens and handle breaking the text of the comment and literal tokens into individual words. +* When the user invokes the _Find Usages_ action, the IDE locates the PSI element the references to be searched. + The PSI element at the cursor (the direct tree parent of the token at the cursor position) must be either a [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) or a [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) which resolves to a [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java). + The word cache will be used to search for the text returned from the [`PsiNamedElement.getName()`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) method. + Also, if the text range of the [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) includes some other text besides the identifier returned from `getName()` (for example, if the [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) represents a JavaScript function and its text range includes the "`function`" keyword in addition to the name of the function), the method `getTextOffset()` must be overridden for the [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java), and must return the start offset of the name identifier within the text range of the element. +* Once the element is located, the IDE calls [`FindUsagesProvider.canFindUsagesFor()`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java) to ask the plugin if the _Find Usages_ action applies to the specific element. +* When showing the _Find Usages_ dialog to the user, [`FindUsagesProvider.getType()`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java) and [`FindUsagesProvider.getDescriptiveName()`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java) are called to determine how the element should be presented to the user. +* For every file containing the searched words, the IDE builds the PSI tree and recursively descends it. + The text of each element is broken into words and then scanned. + If the element was indexed as an identifier, every word is checked to be a [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) resolving to the element the usages of which are searched. + If the element was indexed as a comment or literal and the search in comments or literals is enabled, it checks if the word is equal to the searched element's name. +* After the usages are collected, results are shown in the usages pane. + The text shown for each found element is taken from the [`FindUsagesProvider.getNodeText()`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java) method. -* Before the _Find Usages_ action can be invoked, the IDE builds an index of words present in every file in the custom language. - Using the - [`WordsScanner`](upsource:///platform/indexing-api/src/com/intellij/lang/cacheBuilder/WordsScanner.java) - implementation returned from - [`FindUsagesProvider.getWordsScanner()`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java), - the contents of every file are loaded and passes it to the words scanner, along with the words consumer. - The words scanner breaks the text into words, defines the context for each word (code, comments or literals) and passes the word to the consumer. - The simplest way to implement the words scanner is to use the - [`DefaultWordsScanner`](upsource:///platform/indexing-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java) - implementation, passing to it the sets of lexer token types which are treated as identifiers, literals and comments. - The default words scanner will use the lexer to break the text into tokens, and will handle breaking the text of comment and literal tokens into individual words. - -* When the user invokes the _Find Usages_ action, the IDE locates the PSI element the references to which will be searched. - The PSI element at the cursor (the direct tree parent of the token at the cursor position) must be either a - [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) - or a - [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) - which resolves to a - [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java). - The word cache will be used to search for the text returned from the - [`PsiNamedElement.getName()`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) - method. - Also, if the text range of the - [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) - includes some other text besides the identifier returned from `getName()` (for example, if the - [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) - represents a JavaScript function and its text range includes the "`function`" keyword in addition to the name of the function), the method `getTextOffset()` must be overridden for the - [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java), - and must return the start offset of the name identifier within the text range of the element. - -* Once the element is located, the IDE calls - [`FindUsagesProvider.canFindUsagesFor()`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java) - to ask the plugin if the _Find Usages_ action is applicable to the specific element. - -* When showing the _Find Usages_ dialog to the user, - [`FindUsagesProvider.getType()`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java) - and - [`FindUsagesProvider.getDescriptiveName()`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java) - are called to determine how the element should be presented to the user. - -* For every file containing the searched words, the IDE builds the PSI tree and recursively descends that tree. - The text of each element is broken into words and then scanned. - If the element was indexed as an identifier, every word is checked to be a - [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) - resolving to the element the usages of which are searched. - If the element was indexed as a comment or literal and the search in comments or literals is enabled, it checks if the word is equal to the name of the searched element. - -* After the usages are collected, results are shown in the usages pane. -The text shown for each found element is taken from the -[`FindUsagesProvider.getNodeText()`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java) -method. - -To have the title of the found element be correctly displayed in the title of the Find Usages tool window, you need to provide an implementation of the -[`ElementDescriptionProvider`](upsource:///platform/core-api/src/com/intellij/psi/ElementDescriptionProvider.java) -interface. -The -[`ElementDescriptionLocation`](upsource:///platform/core-api/src/com/intellij/psi/ElementDescriptionLocation.java) -passed to the provider in this case will be an instance of -[`UsageViewLongNameLocation`](upsource:///platform/lang-impl/src/com/intellij/usageView/UsageViewLongNameLocation.java). +To have the title of the found element be correctly displayed in the title of the Find Usages tool window, you need to provide an implementation of the [`ElementDescriptionProvider`](upsource:///platform/core-api/src/com/intellij/psi/ElementDescriptionProvider.java) interface. +The [`ElementDescriptionLocation`](upsource:///platform/core-api/src/com/intellij/psi/ElementDescriptionLocation.java) passed to the provider in this case will be an instance of [`UsageViewLongNameLocation`](upsource:///platform/lang-impl/src/com/intellij/usageView/UsageViewLongNameLocation.java). **Example:** -[`ElementDescriptionProvider`](upsource:///plugins/properties/src/com/intellij/lang/properties/PropertiesDescriptionProvider.java) -for -[Properties language plugin](upsource:///plugins/properties/) +[`ElementDescriptionProvider`](upsource:///plugins/properties/src/com/intellij/lang/properties/PropertiesDescriptionProvider.java) for [Properties language plugin](upsource:///plugins/properties/) -> **TIP** In cases like function parameters and local variables, consider overriding -[`PsiElement.getUseScope()`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) to return a narrower scope. -For instance, you might return just the scope of the nearest function definition. This optimization can greatly reduce -the number of files that need to be parsed--and references that need to be resolved--when renaming a function parameter -or local variable. +> **TIP** In cases like function parameters and local variables, consider overriding [`PsiElement.getUseScope()`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) to return a narrower scope. +> For instance, you might return just the scope of the nearest function definition. +> This optimization can significantly reduce the number of files that need to be parsed--and references that need to be resolved--when renaming a function parameter or local variable. diff --git a/reference_guide/custom_language_support/go_to_class_and_go_to_symbol.md b/reference_guide/custom_language_support/go_to_class_and_go_to_symbol.md index a6bdaf02b..f612ab385 100644 --- a/reference_guide/custom_language_support/go_to_class_and_go_to_symbol.md +++ b/reference_guide/custom_language_support/go_to_class_and_go_to_symbol.md @@ -4,20 +4,14 @@ title: Go to Class and Go to Symbol A custom language plugin can provide its own items to be included in the lists shown when the user chooses the _Navigate | Class_ or _Navigate | Symbol_ action. -In order to do so, the plugin must provide implementations for the -[`ChooseByNameContributor`](upsource:///platform/lang-api/src/com/intellij/navigation/ChooseByNameContributor.java) -interface (separate implementations need to be provided for _Class_ and _Symbol_ respectively), and register them in the `com.intellij.gotoClassContributor` and `com.intellij.gotoSymbolContributor` extension points. +In order to do so, the plugin must provide implementations for the [`ChooseByNameContributor`](upsource:///platform/lang-api/src/com/intellij/navigation/ChooseByNameContributor.java) interface (separate implementations need to be provided for _Class_ and _Symbol_ respectively), and register them in the `com.intellij.gotoClassContributor` and `com.intellij.gotoSymbolContributor` extension points. > **TIP** Please consider implementing [`ChooseByNameContributorEx`](upsource:///platform/lang-impl/src/com/intellij/navigation/ChooseByNameContributorEx.java) for better performance. Each contributor needs to be able to return a complete list of names to show in the list for a specified project, which will then be filtered by the IDE according to the text typed by the user in the dialog. Using [File-based or Stub indices](/basics/indexing_and_psi_stubs.md) to obtain matching candidates is highly recommended to improve performance. -For each name in that list, the contributor needs to provide a list of -[`NavigationItem`](upsource:///platform/core-api/src/com/intellij/navigation/NavigationItem.java) -instances (typically -[`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) -), which specify the destinations to jump to when a specific name is selected from the list. +For each name in that list, the contributor needs to provide a list of [`NavigationItem`](upsource:///platform/core-api/src/com/intellij/navigation/NavigationItem.java) instances (typically [`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java)), which specify the destinations to jump to when a specific name is selected from the list. **Example:** -- [Custom Language Support Tutorial: Go To Symbol Contributor](/tutorials/custom_language_support/go_to_symbol_contributor.md) \ No newline at end of file +- [Custom Language Support Tutorial: Go To Symbol Contributor](/tutorials/custom_language_support/go_to_symbol_contributor.md) diff --git a/reference_guide/custom_language_support/implementing_lexer.md b/reference_guide/custom_language_support/implementing_lexer.md index 79e840a5f..8ac0b4cf8 100644 --- a/reference_guide/custom_language_support/implementing_lexer.md +++ b/reference_guide/custom_language_support/implementing_lexer.md @@ -3,12 +3,9 @@ title: Implementing Lexer --- -The lexer, or -[lexical analyzer](https://en.wikipedia.org/wiki/Lexical_analysis), -defines how the contents of a file is broken into tokens. +The lexer, or [lexical analyzer](https://en.wikipedia.org/wiki/Lexical_analysis), defines how a file's contents are broken into tokens. The lexer serves as a foundation for nearly all of the features of custom language plugins, from basic syntax highlighting to advanced code analysis features. -The API for the lexer is defined by the -[`Lexer`](upsource:///platform/core-api/src/com/intellij/lexer/Lexer.java) interface. +The API for the lexer is defined by the [`Lexer`](upsource:///platform/core-api/src/com/intellij/lexer/Lexer.java) interface. The IDE invokes the lexer in three main contexts, and the plugin can provide different lexer implementations for these contexts: @@ -27,72 +24,42 @@ The IDE invokes the lexer in three main contexts, and the plugin can provide dif [`DefaultWordsScanner`](upsource:///platform/indexing-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java) constructor. -The lexer used for syntax highlighting can be invoked incrementally to process only the changed part of a file, whereas lexers used in other contexts are always called to process an entire file, or a complete language construction embedded in a file in a different language. +The lexer used for syntax highlighting can be invoked incrementally to process only the file's changed part. +In contrast, lexers used in other contexts are always called to process an entire file or a complete language construction embedded in a different language file. A lexer that can be used incrementally may need to return its *state*, which means the context corresponding to each position in a file. -For example, a -[Java lexer](upsource:///java/java-psi-impl/src/com/intellij/lang/java/lexer/JavaLexer.java) -could have separate states for top level context, comment context and string literal context. -An important requirement for a syntax highlighting lexer is that its state must be represented by a single integer number returned from -[`Lexer.getState()`](upsource:///platform/core-api/src/com/intellij/lexer/Lexer.java). -That state will be passed to the -[`Lexer.start()`](upsource:///platform/core-api/src/com/intellij/lexer/Lexer.java) -method, along with the start offset of the fragment to process, when lexing is resumed from the middle of a file. +For example, a [Java lexer](upsource:///java/java-psi-impl/src/com/intellij/lang/java/lexer/JavaLexer.java) could have separate states for top-level context, comment context, and string literal context. +An essential requirement for a syntax highlighting lexer is that its state must be represented by a single integer number returned from [`Lexer.getState()`](upsource:///platform/core-api/src/com/intellij/lexer/Lexer.java). +That state will be passed to the [`Lexer.start()`](upsource:///platform/core-api/src/com/intellij/lexer/Lexer.java) method, along with the start offset of the fragment to process, when lexing is resumed from the middle of a file. Lexers used in other contexts can always return `0` from the `getState()` method. The easiest way to create a lexer for a custom language plugin is to use [JFlex](https://jflex.de). -Classes -[`FlexLexer`](upsource:///platform/core-api/src/com/intellij/lexer/FlexLexer.java) -and -[`FlexAdapter`](upsource:///platform/core-api/src/com/intellij/lexer/FlexAdapter.java) -adapt JFlex lexers to the IntelliJ Platform Lexer API. -We have a -[patched version of JFlex](https://github.com/JetBrains/intellij-deps-jflex) -that can be used with the lexer skeleton file located at *tools/lexer/idea-flex.skeleton* in the -[IntelliJ IDEA Community Edition](https://github.com/JetBrains/intellij-community) -source to create lexers compatible with -[`FlexAdapter`](upsource:///platform/core-api/src/com/intellij/lexer/FlexAdapter.java). -The patched version of JFlex provides a new command line option `--charat` which changes the JFlex generated code so that it works with the IntelliJ Platform skeleton. -Enabling `--charat` option passes the source data for lexing as a -[`CharSequence`](https://docs.oracle.com/javase/8/docs/api/java/lang/CharSequence.html) -and not as an array of characters. - +Classes [`FlexLexer`](upsource:///platform/core-api/src/com/intellij/lexer/FlexLexer.java) and [`FlexAdapter`](upsource:///platform/core-api/src/com/intellij/lexer/FlexAdapter.java) adapt JFlex lexers to the IntelliJ Platform Lexer API. +We have a [patched version of JFlex](https://github.com/JetBrains/intellij-deps-jflex) that can be used with the lexer skeleton file located at *tools/lexer/idea-flex.skeleton* in the [IntelliJ IDEA Community Edition](https://github.com/JetBrains/intellij-community) source to create lexers compatible with [`FlexAdapter`](upsource:///platform/core-api/src/com/intellij/lexer/FlexAdapter.java). +The patched version of JFlex provides a new command-line option `--charat` that changes the JFlex generated code to work with the IntelliJ Platform skeleton. +Enabling `--charat` option passes the source data for lexing as a [`CharSequence`](https://docs.oracle.com/javase/8/docs/api/java/lang/CharSequence.html) and not as an array of characters. For developing lexers using JFlex, the [GrammarKit plugin](https://plugins.jetbrains.com/plugin/6606-grammar-kit) can be useful. It provides syntax highlighting and other useful features for editing JFlex files. -> **NOTE** Lexers, and in particular JFlex-based lexers, need to be created in such a way that they always match the entire contents of the file, without any gaps between tokens, and generate special tokens for characters which are not valid at their location. -Lexers must never abort prematurely because of an invalid character. +> **NOTE** Lexers, and in particular JFlex-based lexers, need to be created so that they always match the entire contents of the file, without any gaps between tokens, and generate special tokens for characters which are not valid at their location. +> Lexers must never abort prematurely because of an invalid character. **Example**: -- [`Lexer`](upsource:///plugins/properties/src/com/intellij/lang/properties/parsing/Properties.flex) -definition for -[Properties language plugin](upsource:///plugins/properties) +- [`Lexer`](upsource:///plugins/properties/src/com/intellij/lang/properties/parsing/Properties.flex) definition for [Properties language plugin](upsource:///plugins/properties) - [Custom Language Support Tutorial: Lexer](/tutorials/custom_language_support/lexer_and_parser_definition.md) -Types of tokens for lexers are defined by instances of -[`IElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IElementType.java). -A number of token types common for all languages are defined in the -[`TokenType`](upsource:///platform/core-api/src/com/intellij/psi/TokenType.java) -interface. +Types of tokens for lexers are defined by instances of [`IElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IElementType.java). +Many token types common for all languages are defined in the [`TokenType`](upsource:///platform/core-api/src/com/intellij/psi/TokenType.java) interface. Custom language plugins should reuse these token types wherever applicable. -For all other token types, the plugin needs to create new -[`IElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IElementType.java) -instances and associate with the language in which the token type is used. -The same -[`IElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IElementType.java) -instance should be returned every time a particular token type is encountered by the lexer. +For all other token types, the plugin needs to create new [`IElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IElementType.java) instances and associate with the language in which the token type is used. +The same [`IElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IElementType.java) instance should be returned every time a particular token type is encountered by the lexer. **Example:** -[Token types](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/PropertiesTokenTypes.java) -for -[Properties language plugin](upsource:///plugins/properties) +[Token types](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/PropertiesTokenTypes.java) for [Properties language plugin](upsource:///plugins/properties) - -An important feature which can be implemented at lexer level is mixing languages within a file, for example, embedding fragments of Java code in some template language. -If a language supports embedding its fragments in another language, it needs to define the chameleon token types for different types of fragments which can be embedded, and these token types need to implement the -[`ILazyParseableElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/ILazyParseableElementType.java) -interface. -The lexer of the enclosing language needs to return the entire fragment of the embedded language as a single chameleon token, of the type defined by the embedded language. -To parse the contents of the chameleon token, the IDE will call the parser of the embedded language through a call to -[`ILazyParseableElementType.parseContents()`](upsource:///platform/core-api/src/com/intellij/psi/tree/ILazyParseableElementType.java). +An important feature that can be implemented at the lexer level is mixing languages within a file, such as embedding fragments of Java code in some template language. +Suppose a language supports embedding its fragments in another language. +In that case, it needs to define the chameleon token types for different types of fragments that can be embedded, and these token types need to implement the [`ILazyParseableElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/ILazyParseableElementType.java) interface. +The enclosing language's lexer needs to return the entire fragment of the embedded language as a single chameleon token, of the type defined by the embedded language. +To parse the contents of the chameleon token, the IDE will call the parser of the embedded language through a call to [`ILazyParseableElementType.parseContents()`](upsource:///platform/core-api/src/com/intellij/psi/tree/ILazyParseableElementType.java). diff --git a/reference_guide/custom_language_support/implementing_parser_and_psi.md b/reference_guide/custom_language_support/implementing_parser_and_psi.md index df0a2f2d3..6ffaa105c 100644 --- a/reference_guide/custom_language_support/implementing_parser_and_psi.md +++ b/reference_guide/custom_language_support/implementing_parser_and_psi.md @@ -5,126 +5,69 @@ title: Implementing a Parser and PSI Parsing files in IntelliJ Platform is a two-step process. First, an abstract syntax tree (AST) is built, defining the structure of the program. -AST nodes are created internally by the IDE and are represented by instances of the -[`ASTNode`](upsource:///platform/core-api/src/com/intellij/lang/ASTNode.java) -class. -Each AST node has an associated element type -[`IElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IElementType.java) -instance, and the element types are defined by the language plugin. -The top-level node of the AST tree for a file needs to have a special element type which extends the -[`IFileElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IFileElementType.java) -class. +AST nodes are created internally by the IDE and are represented by instances of the [`ASTNode`](upsource:///platform/core-api/src/com/intellij/lang/ASTNode.java) class. +Each AST node has an associated element type [`IElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IElementType.java) instance, and the element types are defined by the language plugin. +The AST tree's top-level node for a file needs to have a special element type, which extends the [`IFileElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IFileElementType.java) class. The AST nodes have a direct mapping to text ranges in the underlying document. -The bottom-most nodes of the AST match individual tokens returned by the lexer, and higher level nodes match multiple-token fragments. -Operations performed on nodes of the AST tree, such as inserting, removing, reordering nodes and so on, are immediately reflected as changes to the text of the underlying document. +The bottom-most nodes of the AST match individual tokens returned by the lexer, and higher-level nodes match multiple-token fragments. +Operations performed on nodes of the AST tree, such as inserting, removing, reordering nodes, and so on, are immediately reflected as changes to the underlying document's text. Second, a PSI, or Program Structure Interface, tree is built on top of the AST, adding semantics and methods for manipulating specific language constructs. -Nodes of the PSI tree are represented by classes implementing the -[`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) -interface and are created by the language plugin in the -[`ParserDefinition.createElement()`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java) -method. -The top-level node of the PSI tree for a file needs to implement the -[`PsiFile`](upsource:///platform/core-api/src/com/intellij/psi/PsiFile.java) -interface, and is created in the -[`ParserDefinition.createFile()`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java) -method. +Nodes of the PSI tree are represented by classes implementing the [`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) interface and are created by the language plugin in the [`ParserDefinition.createElement()`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java) method. +The top-level node of the PSI tree for a file needs to implement the [`PsiFile`](upsource:///platform/core-api/src/com/intellij/psi/PsiFile.java) interface and is created in the [`ParserDefinition.createFile()`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java) method. **Example**: -[`ParserDefinition`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesParserDefinition.java) -for -[Properties language plugin](upsource:///plugins/properties) +[`ParserDefinition`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesParserDefinition.java) for [Properties language plugin](upsource:///plugins/properties) +The PSI's lifecycle is described in more detail in [Fundamentals](/platform/fundamentals.md). -The lifecycle of the PSI is described in more detail in [Fundamentals](/platform/fundamentals.md). +The base classes for the PSI implementation, including [`PsiFileBase`](upsource:///platform/core-impl/src/com/intellij/extapi/psi/PsiFileBase.java), the base implementation of [`PsiFile`](upsource:///platform/core-api/src/com/intellij/psi/PsiFile.java), and [`ASTWrapperPsiElement`](upsource:///platform/core-impl/src/com/intellij/extapi/psi/ASTWrapperPsiElement.java), the base implementation of [`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java), are provided by *IntelliJ Platform*. -The base classes for the PSI implementation, including -[`PsiFileBase`](upsource:///platform/core-impl/src/com/intellij/extapi/psi/PsiFileBase.java), -the base implementation of -[`PsiFile`](upsource:///platform/core-api/src/com/intellij/psi/PsiFile.java), -and -[`ASTWrapperPsiElement`](upsource:///platform/core-impl/src/com/intellij/extapi/psi/ASTWrapperPsiElement.java), -the base implementation of -[`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java), -are provided by *IntelliJ Platform*. - -While coding parser manually is quite possible, we highly recommend generating parser and corresponding PSI classes from grammars using -[Grammar-Kit](https://plugins.jetbrains.com/plugin/6606-grammar-kit) plugin. -Besides code generation, it provides various features for editing grammar files: syntax highlighting, quick navigation, refactorings, and more. -The Grammar-Kit plugin is built using its own engine; its source code can be found on -[GitHub](https://github.com/JetBrains/Grammar-Kit). +While coding parser manually is quite possible, we highly recommend generating parser and corresponding PSI classes from grammars using [Grammar-Kit](https://plugins.jetbrains.com/plugin/6606-grammar-kit) plugin. +Besides code generation, it provides various features for editing grammar files: syntax highlighting, quick navigation, refactorings, etc. +The Grammar-Kit plugin is built using its own engine; its source code can be found on [GitHub](https://github.com/JetBrains/Grammar-Kit). For re-using existing ANTLRv4 grammars, see [antlr4-intellij-adaptor](https://github.com/antlr/antlr4-intellij-adaptor) library. -The language plugin provides the parser implementation as an implementation of the -[`PsiParser`](upsource:///platform/core-api/src/com/intellij/lang/PsiParser.java) -interface, returned from -[`ParserDefinition.createParser()`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java). -The parser receives an instance of the -[`PsiBuilder`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) -class, which is used to get the stream of tokens from the lexer and to hold the intermediate state of the AST being built. -The parser must process all tokens returned by the lexer up to the end of stream, in other words until -[`PsiBuilder.getTokenType()`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) -returns `null`, even if the tokens are not valid according to the language syntax. +The language plugin provides the parser implementation as an implementation of the [`PsiParser`](upsource:///platform/core-api/src/com/intellij/lang/PsiParser.java) interface, returned from [`ParserDefinition.createParser()`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java). +The parser receives an instance of the [`PsiBuilder`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) class, which is used to get the stream of tokens from the lexer and to hold the intermediate state of the AST being built. +The parser must process all tokens returned by the lexer up to the end of the stream, in other words, until [`PsiBuilder.getTokenType()`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) returns `null`, even if the tokens are not valid according to the language syntax. **Example**: -[`PsiParser`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesParser.java) -implementation for -[Properties language plugin](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/). +[`PsiParser`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/parsing/PropertiesParser.java) implementation for [Properties language plugin](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/). -The parser works by setting pairs of markers ( -[`PsiBuilder.Marker`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) -instances) within the stream of tokens received from the lexer. +The parser works by setting pairs of markers ( [`PsiBuilder.Marker`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) instances) within the stream of tokens received from the lexer. Each pair of markers defines the range of lexer tokens for a single node in the AST tree. -If a pair of markers is nested in another pair (starts after its start and ends before its end), it becomes the child node of the outer pair. +If a pair of markers is nested in another pair (starts after its start and ends before its end), it becomes the outer pair's child node. -The element type for the marker pair and for the AST node created from it is specified when the end marker is set, which is done by making call to -[`PsiBuilder.Marker.done()`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java). +The element type for the marker pair and for the AST node created from it is specified when the end marker is set, which is done by making the call to [`PsiBuilder.Marker.done()`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java). Also, it is possible to drop a start marker before its end marker has been set. The `drop()` method drops only a single start marker without affecting any markers added after it, and the `rollbackTo()` method drops the start marker and all markers added after it and reverts the lexer position to the start marker. These methods can be used to implement lookahead when parsing. -The method -[`PsiBuilder.Marker.precede()`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) -is useful for right-to-left parsing when you don't know how many markers you need at a certain position until you read more input. +The method [`PsiBuilder.Marker.precede()`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) is useful for right-to-left parsing when you don't know how many markers you need at a specific position until you read more input. For example, a binary expression `a+b+c` needs to be parsed as `( (a+b) + c )`. Thus, two start markers are needed at the position of the token 'a', but that is not known until the token 'c' is read. When the parser reaches the '+' token following 'b', it can call `precede()` to duplicate the start marker at 'a' position, and then put its matching end marker after 'c'. -An important feature of -[`PsiBuilder`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) -is its handling of whitespace and comments. -The types of tokens which are treated as whitespace or comments are defined by the methods `getWhitespaceTokens()` and `getCommentTokens()` in the -[`ParserDefinition`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java) -class. -[`PsiBuilder`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) -automatically omits whitespace and comment tokens from the stream of tokens it passes to -[`PsiParser`](upsource:///platform/core-api/src/com/intellij/lang/PsiParser.java), -and adjusts the token ranges of AST nodes so that leading and trailing whitespace tokens are not included in the node. +An essential feature of [`PsiBuilder`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) is its handling of whitespace and comments. +The types of tokens which are treated as whitespace or comments are defined by the methods `getWhitespaceTokens()` and `getCommentTokens()` in the [`ParserDefinition`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java) class. +[`PsiBuilder`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) automatically omits whitespace and comment tokens from the stream of tokens it passes to [`PsiParser`](upsource:///platform/core-api/src/com/intellij/lang/PsiParser.java) and adjusts the token ranges of AST nodes so that leading and trailing whitespace tokens are not included in the node. -The token set returned from -[`ParserDefinition.getCommentTokens()`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java) -is also used to search for TODO items. +The token set returned from [`ParserDefinition.getCommentTokens()`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java) is also used to search for TODO items. -In order to better understand the process of building a PSI tree for a simple expression, you can refer to the following diagram: +To better understand the process of building a PSI tree for a simple expression, you can refer to the following diagram: ![PsiBuilder](img/PsiBuilder.gif) -In general, there is no single right way to implement a PSI for a custom language, and the plugin author can choose the PSI structure and set of methods which are the most convenient for the code which uses the PSI (error analysis, refactorings and so on). -However, there is one base interface which needs to be used by a custom language PSI implementation in order to support features like rename and find usages. -Every element which can be renamed or referenced (a class definition, a method definition and so on) needs to implement the -[`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) -interface, with methods `getName()` and `setName()`. +In general, there is no single right way to implement a PSI for a custom language, and the plugin author can choose the PSI structure and set of methods that are the most convenient for the code which uses the PSI (error analysis, refactorings, and so on). +However, one base interface needs to be used by a custom language PSI implementation to support features like rename and find usages. +Every element which can be renamed or referenced (a class definition, a method definition and so on) needs to implement the [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) interface, with methods `getName()` and `setName()`. -A number of functions which can be used for implementing and using the PSI can be found in the `com.intellij.psi.util` package, and in particular in the -[`PsiUtilCore`](upsource:///platform/core-api/src/com/intellij/psi/util/PsiUtilCore.java) -and -[`PsiTreeUtil`](upsource:///platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java) -classes. +Several functions which can be used for implementing and using the PSI can be found in the `com.intellij.psi.util` package, and in particular in the [`PsiUtilCore`](upsource:///platform/core-api/src/com/intellij/psi/util/PsiUtilCore.java) and [`PsiTreeUtil`](upsource:///platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java) classes. -> **TIP** A very helpful tool for debugging the PSI implementation is the [PsiViewer plugin](https://plugins.jetbrains.com/plugin/227-psiviewer). It can show you the structure of the PSI built by your plugin, the properties of every PSI element and highlight its text range. +> **TIP** A useful tool for debugging the PSI implementation is the [PsiViewer plugin](https://plugins.jetbrains.com/plugin/227-psiviewer). +> It can show you the PSI structure built by your plugin, the properties of every PSI element, and highlight its text range. -Please see -[Indexing and PSI Stubs](/basics/indexing_and_psi_stubs.md) -for advanced topics. +Please see [Indexing and PSI Stubs](/basics/indexing_and_psi_stubs.md) for advanced topics. diff --git a/reference_guide/custom_language_support/references_and_resolve.md b/reference_guide/custom_language_support/references_and_resolve.md index 98cab3319..f7f64c596 100644 --- a/reference_guide/custom_language_support/references_and_resolve.md +++ b/reference_guide/custom_language_support/references_and_resolve.md @@ -4,86 +4,54 @@ title: References and Resolve One of the most important and tricky parts in implementing a custom language PSI is resolving references. -Resolving references gives users the ability to navigate from a PSI element usage (accessing a variable, calling a method and so on) to the declaration of that element (the variable's definition, a method declaration and so on). +Resolving references gives users the ability to navigate from a PSI element usage (accessing a variable, calling a method, etc.) to the declaration of that element (the variable's definition, a method declaration, and so on). This feature is needed in order to support the _Go to Declaration_ action invoked by **Ctrl-B** and **Ctrl-Click**, and it is a prerequisite for implementing the [Find Usages](find_usages.md) action, the [Rename Refactoring](rename_refactoring.md) and [Code Completion](code_completion.md). > **NOTE** The _Quick Definition_ action is based on the same mechanism, so it becomes automatically available for all references that can be resolved by the language plugin. All PSI elements which work as references (for which the _Go to Declaration_ action applies) need to implement the -[`PsiElement.getReference()`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) -method and to return a -[`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) -implementation from that method. -The -[`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) -interface can be implemented by the same class as -[`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java), -or by a different class. An element can also contain multiple references (for example, a string literal can contain multiple substrings which are valid full-qualified class names), in which case it can implement -[`PsiElement.getReferences()`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) -and return the references as an array. +[`PsiElement.getReference()`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) method and to return a [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) implementation from that method. +The [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) interface can be implemented by the same class as [`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java), or by a different class. +An element can also contain multiple references (for example, a string literal can contain multiple substrings which are valid fully-qualified class names), in which case it can implement [`PsiElement.getReferences()`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) and return the references as an array. -The main method of the -[`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) -interface is `resolve()`, which returns the element to which the reference points, or `null` if it was not possible to resolve the reference to a valid element (for example, should it point to an undefined class). The resolved element should implement the [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) interface. +The primary method of the [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) interface is `resolve()`, which returns the element to which the reference points, or `null` if it was not possible to resolve the reference to a valid element (for example, should it point to an undefined class). +The resolved element should implement the [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) interface. -> **NOTE** While it may occur that the referencing element and the referenced element both have a name, only the element which **introduces** the name (e.g. the definition `int x = 42`) needs to implement the [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) interface. The referencing element at the point of usage (e.g. the `x` in the expression `x + 1`) should not implement `PsiNamedElement` since it itself does not _have_ a name. +> **NOTE** While the referencing element and the referenced element both may have a name, only the element which **introduces** the name (e.g., the definition `int x = 42`) needs to implement the [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) interface. +> The referencing element at the point of usage (e.g., the `x` in the expression `x + 1`) should not implement `PsiNamedElement` since it does not _have_ a name. > **TIP** In order to enable more advanced IntelliJ functionality, prefer implementing [`PsiNameIdentifierOwner`](upsource:///platform/core-api/src/com/intellij/psi/PsiNameIdentifierOwner.java) over [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) where possible. -A counterpart to the `resolve()` method is `isReferenceTo()`, which checks if the reference resolves to the specified element. The latter method can be implemented by calling `resolve()` and comparing the result with the passed PSI element, but additional optimizations are possible (for example, performing the tree walk only if the element text is equal to the text of the reference). +A counterpart to the `resolve()` method is `isReferenceTo()`, which checks if the reference resolves to the specified element. +The latter method can be implemented by calling `resolve()` and comparing the result with the passed PSI element. +Still, additional optimizations are possible (for example, performing the tree walk only if the element text is equal to the text of the reference). **Examples**: -- [Reference](upsource:///plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java) -to a ResourceBundle in the -[Properties language plugin](upsource:///plugins/properties) +- [Reference](upsource:///plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java) to a ResourceBundle in the [Properties language plugin](upsource:///plugins/properties) - [Custom Language Support Tutorial: Reference Contributor](/tutorials/custom_language_support/reference_contributor.md) -> **TIP** To optimize `getReferences()` performance, consider implementing [`HintedReferenceHost`](upsource:///platform/core-api/src/com/intellij/psi/HintedReferenceHost.java) to provide additional hints. Please see also _Cache Results of Heavy Computations_ in [Working with PSI efficiently](/reference_guide/performance/performance.md#working-with-psi-efficiently). +> **TIP** To optimize `getReferences()` performance, consider implementing [`HintedReferenceHost`](upsource:///platform/core-api/src/com/intellij/psi/HintedReferenceHost.java) to provide additional hints. +> Please see also _Cache Results of Heavy Computations_ in [Working with PSI efficiently](/reference_guide/performance/performance.md#working-with-psi-efficiently). -There's a set of interfaces which can be used as a base for implementing resolve support, namely the -[`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) interface and the -[`PsiElement.processDeclarations()`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) -method. -These interfaces have a number of extra complexities which are not necessary for most custom languages (like support for substituting Java generics types), but they are required if the custom language can have references to Java code. +There are a set of interfaces that can be used as a base for implementing resolve support, namely the [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) interface and the [`PsiElement.processDeclarations()`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) method. +These interfaces have several extra complexities that are unnecessary for most custom languages (like support for substituting Java generics types). +Still, they are required if the custom language can have references to Java code. If Java interoperability is not required, the plugin can forgo the standard interfaces and provide its own, different implementation of resolve. -The implementation of resolve based on the standard helper classes contains of the following components: +The implementation of resolve based on the standard helper classes contains the following components: -* A class implementing the - [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) - interface which gathers the possible declarations for the reference and stops the resolve process when it has successfully completed. - The main method which needs to be implemented is `execute()`, which is called to process every declaration encountered during the resolve, and returns `true` if the resolve needs to be continued or `false` if the declaration has been found. - The methods `getHint()` and `handleEvent()` are used for internal optimizations and can be left empty in the - [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) - implementations for custom languages. - -* A function which walks the PSI tree up from the reference location until the resolve has successfully completed or until the end of the resolve scope has been reached. - If the target of the reference is located in a different file, the file can be located, for example, using - [`FilenameIndex.getFilesByName()`](upsource:///platform/indexing-api/src/com/intellij/psi/search/FilenameIndex.java) - (if the file name is known) or by iterating through all custom language files in the project (`iterateContent()` in the - [`ProjectFileIndex`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java) - interface obtained from - [`ProjectRootManager.getFileIndex()`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ProjectRootManager.java) - ). - -* The individual PSI elements, on which the `processDeclarations()` method is called during the PSI tree walk. - If a PSI element is a declaration, it passes itself to the `execute()` method of the - [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) - passed to it. - Also, if necessary according to the language scoping rules, a PSI element can pass the - [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) - to its child elements. +* A class implements the [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) interface, which gathers the possible declarations for the reference and stops the resolve process when it has successfully completed. + The primary method which needs to be implemented is `execute()`, which is called to process every declaration encountered during the resolve, and returns `true` if the resolve needs to be continued or `false` if the declaration has been found. + The methods `getHint()` and `handleEvent()` are used for internal optimizations and can be left empty in the [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) implementations for custom languages. +* A function which walks the PSI tree up from the reference location until the resolve has successfully completed or until the end of the resolve scope has been reached. + If the target of the reference is located in a different file, the file can be located, for example, using [`FilenameIndex.getFilesByName()`](upsource:///platform/indexing-api/src/com/intellij/psi/search/FilenameIndex.java) (if the file name is known) or by iterating through all custom language files in the project (`iterateContent()` in the [`ProjectFileIndex`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java) interface obtained from [`ProjectRootManager.getFileIndex()`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ProjectRootManager.java)). +* The individual PSI elements, on which the `processDeclarations()` method is called during the PSI tree walk. + If a PSI element is a declaration, it passes itself to the `execute()` method of the [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) passed to it. + Also, if necessary, according to the language scoping rules, a PSI element can pass the [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java) to its child elements. ### Resolving to Multiple Targets -An extension of the -[`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) -interface, which allows a reference to resolve to multiple targets, is the -[`PsiPolyVariantReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiPolyVariantReference.java) -interface. +An extension of the [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) interface, which allows a reference to resolve to multiple targets, is the [`PsiPolyVariantReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiPolyVariantReference.java) interface. The targets to which the reference resolves are returned from the `multiResolve()` method. The _Go to Declaration_ action for such references allows the user to choose a navigation target. -The implementation of `multiResolve()` can be also based on -[`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java), -and can collect all valid targets for the reference instead of stopping when the first valid target is found. - +The implementation of `multiResolve()` can be also based on [`PsiScopeProcessor`](upsource:///platform/core-api/src/com/intellij/psi/scope/PsiScopeProcessor.java), and can collect all valid targets for the reference instead of stopping when the first valid target is found. diff --git a/reference_guide/custom_language_support/registering_file_type.md b/reference_guide/custom_language_support/registering_file_type.md index 3641b0e70..b63566735 100644 --- a/reference_guide/custom_language_support/registering_file_type.md +++ b/reference_guide/custom_language_support/registering_file_type.md @@ -5,27 +5,18 @@ title: Registering a File Type The first step in developing a custom language plugin is registering a file type associated with the language. -The IDE normally determines the type of a file by looking at its file name or extension. +The IDE typically determines the type of a file by looking at its file name or extension. In 2020.2, support for mapping via _hashbang_ is available via `hashBangs` attribute in `com.intellij.fileType` extension point. -A custom language file type is a class derived from -[`LanguageFileType`](upsource:///platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java), -which passes a -[`Language`](upsource:///platform/core-api/src/com/intellij/lang/Language.java) -subclass to its base class constructor. +A custom language file type is a class derived from [`LanguageFileType`](upsource:///platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java), which passes a [`Language`](upsource:///platform/core-api/src/com/intellij/lang/Language.java) subclass to its base class constructor. -To register a file type, the plugin developer provides a subclass of -[`FileTypeFactory`](upsource:///platform/platform-api/src/com/intellij/openapi/fileTypes/FileTypeFactory.java), which is registered via the `com.intellij.fileTypeFactory` extension point. +To register a file type, the plugin developer provides a subclass of [`FileTypeFactory`](upsource:///platform/platform-api/src/com/intellij/openapi/fileTypes/FileTypeFactory.java), which is registered via the `com.intellij.fileTypeFactory` extension point. > **NOTE** When targeting 2019.2 or later only, using `com.intellij.fileType` extension point is preferred to using dedicated `FileTypeFactory`. **Examples**: -- [`LanguageFileType`](upsource:///platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java) -subclass in -[Properties language plugin](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesFileType.java) +- [`LanguageFileType`](upsource:///platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java) subclass in [Properties language plugin](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesFileType.java) - [Custom Language Support Tutorial: Language and File Type](/tutorials/custom_language_support/language_and_filetype.md) -To verify that the file type is registered correctly, you can implement the -[`LanguageFileType.getIcon()`](upsource:///platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java) -method and verify that the correct icon (see [Working with Icons and Images](/reference_guide/work_with_icons_and_images.md)) is displayed for files associated with your file type. +To verify that the file type is registered correctly, you can implement the [`LanguageFileType.getIcon()`](upsource:///platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java) method and verify that the correct icon (see [Working with Icons and Images](/reference_guide/work_with_icons_and_images.md)) is displayed for files associated with your file type. If you want IDEs to show a hint prompting users that your plugin supports a specific file type, see [Plugin Recommendations](https://plugins.jetbrains.com/docs/marketplace/intellij-plugin-recommendations.html). diff --git a/reference_guide/custom_language_support/rename_refactoring.md b/reference_guide/custom_language_support/rename_refactoring.md index c338e1c59..5bad281bb 100644 --- a/reference_guide/custom_language_support/rename_refactoring.md +++ b/reference_guide/custom_language_support/rename_refactoring.md @@ -3,17 +3,13 @@ title: Rename Refactoring --- -The operation of the Rename refactoring is quite similar to that of [Find Usages](find_usages.md). -It uses the same rules for locating the element to be renamed, and the same index of words for locating the files which may have references to the element being renamed. +The Rename refactoring operation is quite similar to that of [Find Usages](find_usages.md). +It uses the same rules for locating the element to be renamed and the same index of words for finding the files that may have references to the element being renamed. -When the rename refactoring is performed, the method -[`PsiNamedElement.setName()`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) -is called for the renamed element, and -[`PsiReference.handleElementRename()`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) -is called for all references to the renamed element. -Both of these methods perform basically the same action: replace the underlying AST node of the PSI element with the node containing the new text entered by the user. -Creating a fully correct AST node from scratch is quite difficult. -Thus, surprisingly, the easiest way to get the replacement node is to create a dummy file in the custom language so that it would contain the necessary node in its parse tree, build the parse tree and extract the necessary node from it. +When the rename refactoring is performed, the method [`PsiNamedElement.setName()`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) is called for the renamed element, and [`PsiReference.handleElementRename()`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) is called for all references to the renamed element. +These methods perform basically the same action: replace the underlying AST node of the PSI element with the node containing the new text entered by the user. +Creating an entirely correct AST node from scratch is quite tricky. +Thus, surprisingly, the easiest way to get the replacement node is to create a dummy file in the custom language so that it would contain the necessary node in its parse tree, build the parse tree and extract the required node from it. **Examples:** - [`setName()`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java) implementation for a [Properties language plugin](upsource:///plugins/properties) @@ -25,41 +21,24 @@ If an implementation of this interface is not provided by the plugin, Java rules Implementations of `NamesValidator` are registered in the `com.intellij.lang.namesValidator` extension point. **Example**: -[`PropertiesNamesValidator`](upsource:///plugins/properties/src/com/intellij/lang/properties/PropertiesNamesValidator.java) -for -[Properties language plugin](upsource:///plugins/properties) +[`PropertiesNamesValidator`](upsource:///plugins/properties/src/com/intellij/lang/properties/PropertiesNamesValidator.java) for [Properties language plugin](upsource:///plugins/properties) ### Custom Rename UI and Workflow Further customization of the Rename refactoring processing is possible on multiple levels. -Providing a custom implementation of the -[`RenameHandler`](upsource:///platform/lang-api/src/com/intellij/refactoring/rename/RenameHandler.java) -interface allows you to entirely replace the UI and workflow of the rename refactoring, and also to support renaming something which is not a -[`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) -at all. +Providing a custom implementation of the [`RenameHandler`](upsource:///platform/lang-api/src/com/intellij/refactoring/rename/RenameHandler.java) interface allows you to entirely replace the UI and workflow of the rename refactoring, and also to support renaming something which is not a [`PsiElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiElement.java) at all. **Example**: -[`RenameHandler`](upsource:///plugins/properties/properties-resource-bundle-editor/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java) -for renaming a resource bundle in the -[Properties language plugin](upsource:///plugins/properties) +[`RenameHandler`](upsource:///plugins/properties/properties-resource-bundle-editor/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java) for renaming a resource bundle in the [Properties language plugin](upsource:///plugins/properties) - -If you're fine with the standard UI but need to extend the default logic of renaming, you can provide an implementation of the -[`RenamePsiElementProcessor`](upsource:///platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiElementProcessor.java) -interface. +If you're okay with the standard UI but need to extend the default logic of renaming, you can provide an implementation of the [`RenamePsiElementProcessor`](upsource:///platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiElementProcessor.java) interface. This allows you to: -* Rename an element different from the one on which the action was invoked (a super method, for example) - -* Rename multiple elements at once (if their names are linked according to the logic of your language) - -* Check for name conflicts (existing names etc.) - -* Customize how search for code references or text references is performed - -* etc. +* Rename an element different from the one on which the action was invoked (a super method, for example) +* Rename multiple elements at once (if their names are linked according to the logic of your language) +* Check for name conflicts (existing names, etc.) +* Customize how a search for code references or text references is performed +* etc. **Example**: -[`RenamePsiElementProcessor`](upsource:///plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java) -for renaming a property in -[Properties plugin language](upsource:///plugins/properties) +[`RenamePsiElementProcessor`](upsource:///plugins/properties/src/com/intellij/lang/properties/refactoring/rename/RenamePropertyProcessor.java) for renaming a property in [Properties plugin language](upsource:///plugins/properties) diff --git a/reference_guide/custom_language_support/safe_delete_refactoring.md b/reference_guide/custom_language_support/safe_delete_refactoring.md index d306b544c..fd7986bdd 100644 --- a/reference_guide/custom_language_support/safe_delete_refactoring.md +++ b/reference_guide/custom_language_support/safe_delete_refactoring.md @@ -20,16 +20,9 @@ In addition to that, to support _Safe Delete_, a plugin needs to implement two t **Example:** -[`delete()`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java) -implementation for a Property in -[Properties language plugin](upsource:///plugins/properties/) - - -If needed, it's possible to further customize how _Safe Delete_ is performed for a particular type of element (e.g., how references are searched) -via [`SafeDeleteProcessorDelegate`](upsource:///platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessorDelegate.java). +[`delete()`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertyImpl.java) implementation for a Property in [Properties language plugin](upsource:///plugins/properties/) +If needed, it's possible to further customize how _Safe Delete_ is performed for a particular type of element (e.g., how references are searched) via [`SafeDeleteProcessorDelegate`](upsource:///platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessorDelegate.java). **Example**: -[`SafeDeleteProcessorDelegate`](upsource:///plugins/properties/src/com/intellij/lang/properties/refactoring/PropertiesFilesSafeDeleteProcessor.java) -implementation for -[Properties language plugin](upsource:///plugins/properties) +[`SafeDeleteProcessorDelegate`](upsource:///plugins/properties/src/com/intellij/lang/properties/refactoring/PropertiesFilesSafeDeleteProcessor.java) implementation for [Properties language plugin](upsource:///plugins/properties) diff --git a/reference_guide/custom_language_support/structure_view.md b/reference_guide/custom_language_support/structure_view.md index 8090381ac..723177dec 100644 --- a/reference_guide/custom_language_support/structure_view.md +++ b/reference_guide/custom_language_support/structure_view.md @@ -4,55 +4,32 @@ title: Structure View The Structure View implementation used for a specific file type can be customized on many levels. -If a custom language plugin provides an implementation of the -[`StructureView`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureView.java) -interface, it can completely replace the standard structure view implementation with a custom user interface component. -However, for most languages this is not necessary, and the standard -[`StructureView`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureView.java) -implementation provided by *IntelliJ Platform* can be reused. +If a custom language plugin provides an implementation of the [`StructureView`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureView.java) interface, it can completely replace the standard structure view implementation with a custom user interface component. +However, for most languages, this is not necessary, and the standard [`StructureView`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureView.java) implementation provided by *IntelliJ Platform* can be reused. -The starting point for the structure view is the -[`PsiStructureViewFactory`](upsource:///platform/editor-ui-api/src/com/intellij/lang/PsiStructureViewFactory.java) -interface, which is registered in the `com.intellij.lang.psiStructureViewFactory` extension point. +The starting point for the structure view is the [`PsiStructureViewFactory`](upsource:///platform/editor-ui-api/src/com/intellij/lang/PsiStructureViewFactory.java) interface, which is registered in the `com.intellij.lang.psiStructureViewFactory` extension point. **Examples:** -- [`PsiStructureViewFactory`](upsource:///plugins/properties/src/com/intellij/lang/properties/structureView/PropertiesStructureViewBuilderFactory.java) -for -[Properties language plugin](upsource:///plugins/properties) +- [`PsiStructureViewFactory`](upsource:///plugins/properties/src/com/intellij/lang/properties/structureView/PropertiesStructureViewBuilderFactory.java) for [Properties language plugin](upsource:///plugins/properties) - [Custom Language Support Tutorial: Structure View](/tutorials/custom_language_support/structure_view_factory.md) -To reuse the *IntelliJ Platform* implementation of the -[`StructureView`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureView.java), -the plugin returns a -[`TreeBasedStructureViewBuilder`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/TreeBasedStructureViewBuilder.java) -from its -[`PsiStructureViewFactory.getStructureViewBuilder()`](upsource:///platform/editor-ui-api/src/com/intellij/lang/PsiStructureViewFactory.java) -method. -As the model for the builder, the plugin can specify a subclass of -[`TextEditorBasedStructureViewModel`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/TextEditorBasedStructureViewModel.java), -and by overriding methods of this subclass it customizes the structure view for a specific language. +To reuse the *IntelliJ Platform* implementation of the [`StructureView`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureView.java), the plugin returns a [`TreeBasedStructureViewBuilder`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/TreeBasedStructureViewBuilder.java) from its [`PsiStructureViewFactory.getStructureViewBuilder()`](upsource:///platform/editor-ui-api/src/com/intellij/lang/PsiStructureViewFactory.java) method. +As the builder model, the plugin can specify a subclass of [`TextEditorBasedStructureViewModel`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/TextEditorBasedStructureViewModel.java), and by overriding methods of this subclass, it customizes the structure view for a specific language. **Example**: -[`StructureViewModel`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesFileStructureViewModel.java) -for -[Properties language plugin](upsource:///plugins/properties) +[`StructureViewModel`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesFileStructureViewModel.java) for [Properties language plugin](upsource:///plugins/properties) -The main method to override is `getRoot()`, which returns the instance of a class implementing the -[`StructureViewTreeElement`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureViewTreeElement.java) -interface. +The main method to override is `getRoot()`, which returns the instance of a class implementing the [`StructureViewTreeElement`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureViewTreeElement.java) interface. There exists no standard implementation of this interface, so a plugin will need to implement it completely. The structure view tree is usually built as a partial mirror of the PSI tree. -In the implementation of -`StructureViewTreeElement.getChildren()`, -the plugin can specify which of the child elements of a specific PSI tree node need to be represented as elements in the structure view. +In the implementation of `StructureViewTreeElement.getChildren()`, the plugin can specify which of the child elements of a specific PSI tree node need to be represented as elements in the structure view. Another important method is `getPresentation()`, which can be used to customize the text, attributes, and icon used to represent an element in the structure view. The implementation of `StructureViewTreeElement.getChildren()` needs to be matched by `TextEditorBasedStructureViewModel.getSuitableClasses()`. -The latter method returns an array of `PsiElement`\-derived classes which can be shown as structure view elements. It is used to select the Structure View item matching the cursor position when the structure view is first opened or when the _Autoscroll from source_ option is enabled. +The latter method returns an array of `PsiElement`\-derived classes, which can be shown as structure view elements. +It is used to select the Structure View item matching the cursor position when the structure view is first opened or when the _Autoscroll from source_ option is enabled. **Example:** -[`StructureViewTreeElement`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/PropertyStructureViewElement.java) -for -[Properties language plugin](upsource:///plugins/properties/) +[`StructureViewTreeElement`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/PropertyStructureViewElement.java) for [Properties language plugin](upsource:///plugins/properties/) diff --git a/reference_guide/custom_language_support/surround_with.md b/reference_guide/custom_language_support/surround_with.md index 95b82947a..3fc8861fd 100644 --- a/reference_guide/custom_language_support/surround_with.md +++ b/reference_guide/custom_language_support/surround_with.md @@ -3,22 +3,13 @@ title: Surround With --- -To support the _Surround With_ action, the plugin needs to register one or more implementations of the -[`SurroundDescriptor`](upsource:///platform/lang-api/src/com/intellij/lang/surroundWith/SurroundDescriptor.java) -interface in the `com.intellij.lang.surroundDescriptor` extension point. -Each of the surround descriptors defines a possible type of code fragment which can be surrounded - for example, one surround descriptor can handle surrounding expressions, and another can handle statements. -Each surround descriptor, in turn, contains an array of -[`Surrounder`](upsource:///platform/lang-api/src/com/intellij/lang/surroundWith/Surrounder.java) -objects, defining specific templates which can be used for surrounding the selected code fragment (for example, _Surround With if_, _Surround With for_, and so on). +To support the _Surround With_ action, the plugin needs to register one or more implementations of the [`SurroundDescriptor`](upsource:///platform/lang-api/src/com/intellij/lang/surroundWith/SurroundDescriptor.java) interface in the `com.intellij.lang.surroundDescriptor` extension point. +Each of the surround descriptors defines a possible type of code fragment that can be surrounded - for example, one surround descriptor can handle surrounding expressions, and another can handle statements. +Each surround descriptor, in turn, contains an array of [`Surrounder`](upsource:///platform/lang-api/src/com/intellij/lang/surroundWith/Surrounder.java) objects, defining specific templates which can be used for surrounding the selected code fragment (for example, _Surround With if_, _Surround With for_, and so on). When the _Surround With_ action is invoked, the IDE queries all surround descriptors for the language until it finds one that returns a non-empty array from its `getElementsToSurround()` method. -Then it calls the -[`Surrounder.isApplicable()`](upsource:///platform/lang-api/src/com/intellij/lang/surroundWith/Surrounder.java) -method for each surrounder in that descriptor to check if the specific template is applicable in the current context. -Once the user selects a specific surrounder from the popup menu, the -[`Surrounder.surroundElements()`](upsource:///platform/lang-api/src/com/intellij/lang/surroundWith/Surrounder.java) -method is used to execute the surround action. +Then it calls the [`Surrounder.isApplicable()`](upsource:///platform/lang-api/src/com/intellij/lang/surroundWith/Surrounder.java) method for each surrounder in that descriptor to check if the specific template is applicable in the current context. +Once the user selects a specific surrounder from the popup menu, the [`Surrounder.surroundElements()`](upsource:///platform/lang-api/src/com/intellij/lang/surroundWith/Surrounder.java) method is used to execute the surround action. **Example:** -[`SurroundDescriptor`](upsource:///plugins/groovy/src/org/jetbrains/plugins/groovy/lang/surroundWith/GroovySurroundDescriptor.java) -for Groovy plugin \ No newline at end of file +[`SurroundDescriptor`](upsource:///plugins/groovy/src/org/jetbrains/plugins/groovy/lang/surroundWith/GroovySurroundDescriptor.java) for Groovy plugin diff --git a/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md b/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md index 8c1bdd1a6..7761b34ec 100644 --- a/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md +++ b/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md @@ -3,101 +3,67 @@ title: Syntax Highlighting and Error Highlighting --- -The class used to specify how a particular range of text should be highlighted is called -[`TextAttributesKey`](upsource:///platform/core-api/src/com/intellij/openapi/editor/colors/TextAttributesKey.java). -An instance of this class is created for every distinct type of item which should be highlighted (keyword, number, string and so on). -The `TextAttributesKey` defines the default attributes which are applied to items of the corresponding type (for example, keywords are bold, numbers are blue, strings are bold and green). -The mapping of the `TextAttributesKey` to specific attributes used in an editor is defined by the -[`EditorColorsScheme`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java) -class, and can be configured by the user if the plugin provides an appropriate configuration interface. -Highlighting from multiple `TextAttributesKey` items can be layered - for example, one key may define an item's boldness and another its color. +The class used to specify how a particular range of text should be highlighted is called [`TextAttributesKey`](upsource:///platform/core-api/src/com/intellij/openapi/editor/colors/TextAttributesKey.java). +An instance of this class is created for every distinct type of item that should be highlighted (keyword, number, string, etc.). +The `TextAttributesKey` defines the default attributes applied to items of the corresponding type (for example, keywords are bold, numbers are blue, strings are bold and green). +The mapping of the `TextAttributesKey` to specific attributes used in an editor is defined by the [`EditorColorsScheme`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java) class. +It can be configured by the user if the plugin provides an appropriate configuration interface. +Highlighting from multiple `TextAttributesKey` items can be layered - for example, one key may define an item's boldness and another color. **Note:** -New functionality about Language Defaults and support for additional color schemes as detailed in -[Color Scheme Management](/reference_guide/color_scheme_management.md). +New functionality about Language Defaults and support for additional color schemes as detailed in [Color Scheme Management](/reference_guide/color_scheme_management.md). - -> **TIP** To force re-highlighting, use +> **TIP** To force re-highlighting, use > [`DaemonCodeAnalyzer.restart()`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzer.java). -The syntax and error highlighting is performed on multiple levels: Lexer, Parser and (External) Annotator. +The syntax and error highlighting are performed on multiple levels: Lexer, Parser, and (External) Annotator. ### Lexer -The first level of syntax highlighting is based on the lexer output, and is provided through the -[`SyntaxHighlighter`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighter.java) -interface. -The syntax highlighter returns the `TextAttributesKey` instances for each token type which needs special highlighting. -For highlighting lexer errors, the standard `TextAttributesKey` for bad characters -[`HighlighterColors.BAD_CHARACTER`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/HighlighterColors.java) -can be used. +The first syntax highlighting level is based on the lexer output and is provided through the [`SyntaxHighlighter`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighter.java) interface. +The syntax highlighter returns the `TextAttributesKey` instances for each token type, which needs special highlighting. +For highlighting lexer errors, the standard `TextAttributesKey` for bad characters [`HighlighterColors.BAD_CHARACTER`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/HighlighterColors.java) can be used. **Examples:** -- [`SyntaxHighlighter`](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlighter.java) -implementation for -[Properties language plugin](upsource:///plugins/properties/) +- [`SyntaxHighlighter`](upsource:///plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlighter.java) implementation for [Properties language plugin](upsource:///plugins/properties/) - [Custom Language Support Tutorial: Syntax Highlighter](/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md) ### Parser The second level of error highlighting happens during parsing. -If a particular sequence of tokens is invalid according to the grammar of the language, the -[`PsiBuilder.error()`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) -method can be used to highlight the invalid tokens and display an error message showing why they are not valid. +If a particular sequence of tokens is invalid according to the grammar of the language, the [`PsiBuilder.error()`](upsource:///platform/core-api/src/com/intellij/lang/PsiBuilder.java) method can highlight the invalid tokens and display an error message showing why they are not valid. ### Annotator -The third level of highlighting is performed through the -[`Annotator`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/Annotator.java) -interface. -A plugin can register one or more annotators in the `com.intellij.annotator` extension point, and these annotators are called during the background highlighting pass to process the elements in the PSI tree of the custom language. +The third level of highlighting is performed through the [`Annotator`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/Annotator.java) interface. +A plugin can register one or more annotators in the `com.intellij.annotator` extension point, and these annotators are called during the background highlighting pass to process the elements in the custom language's PSI tree. Annotators can analyze not only the syntax, but also the semantics using PSI, and thus can provide much more complex syntax and error highlighting logic. The annotator can also provide quick fixes to problems it detects. When the file is changed, the annotator is called incrementally to process only changed elements in the PSI tree. -To highlight a region of text as a warning or error, the annotator calls `createErrorAnnotation()` or `createWarningAnnotation()` on the -[`AnnotationHolder`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/AnnotationHolder.java) -object passed to it, and optionally calls `registerFix()` on the returned -[`Annotation`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/Annotation.java) -object to add a quick fix for the error or warning. -To apply additional syntax highlighting, the annotator can call -[`AnnotationHolder.createInfoAnnotation()`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/AnnotationHolder.java) -with an empty message and then call -[`Annotation.setTextAttributes()`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/Annotation.java) -to specify the text attributes key for the highlighting. +To highlight a region of text as a warning or error, the annotator calls `createErrorAnnotation()` or `createWarningAnnotation()` on the [`AnnotationHolder`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/AnnotationHolder.java) object passed to it, and optionally calls `registerFix()` on the returned [`Annotation`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/Annotation.java) object to add a quick fix for the error or warning. +To apply additional syntax highlighting, the annotator can call [`AnnotationHolder.createInfoAnnotation()`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/AnnotationHolder.java) with an empty message and then call [`Annotation.setTextAttributes()`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/Annotation.java) to specify the text attributes key for the highlighting. > **NOTE** See also [Code Inspections](code_inspections_and_intentions.md) which offer a more fine-grained control and some additional features. **Examples:** -- [`Annotator`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesAnnotator.java) -for -[Properties language plugin](upsource:///plugins/properties/) +- [`Annotator`](upsource:///plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesAnnotator.java) for [Properties language plugin](upsource:///plugins/properties/) - [Custom Language Support Tutorial: Annotator](/tutorials/custom_language_support/annotator.md) ### External Tool -Finally, if the custom language employs external tools for validating files in the language (for example, uses the Xerces library for XML schema validation), it can provide an implementation of the -[`ExternalAnnotator`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/ExternalAnnotator.java) -interface and register it in `com.intellij.externalAnnotator` extension point. -The -[`ExternalAnnotator`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/ExternalAnnotator.java) -highlighting has the lowest priority and is invoked only after all other background processing has completed. -It uses the same -[`AnnotationHolder`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/AnnotationHolder.java) -interface for converting the output of the external tool into editor highlighting. +Finally, if the custom language employs external tools for validating files in the language (for example, uses the Xerces library for XML schema validation), it can provide an implementation of the [`ExternalAnnotator`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/ExternalAnnotator.java) interface and register it in `com.intellij.externalAnnotator` extension point. +The [`ExternalAnnotator`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/ExternalAnnotator.java) highlighting has the lowest priority and is invoked only after all other background processing has completed. +It uses the same [`AnnotationHolder`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/AnnotationHolder.java) interface for converting the output of the external tool into editor highlighting. ## Color Settings The plugin can also provide a configuration interface to allow the user to configure the colors used for highlighting specific items. -In order to do that, it should provide an implementation of -[`ColorSettingPage`](upsource:///platform/platform-api/src/com/intellij/openapi/options/colors/ColorSettingsPage.java) -and register it in the `com.intellij.colorSettingsPage` extension point. +In order to do that, it should provide an implementation of [`ColorSettingPage`](upsource:///platform/platform-api/src/com/intellij/openapi/options/colors/ColorSettingsPage.java) and register it in the `com.intellij.colorSettingsPage` extension point. -The _Export to HTML_ feature uses the same syntax highlighting mechanism as the editor, so it will work automatically for custom languages which provide a syntax highlighter. +The _Export to HTML_ feature uses the same syntax highlighting mechanism as the editor, so it will work automatically for custom languages, which provide a syntax highlighter. **Examples**: -- [`ColorSettingsPage`](upsource:///plugins/properties/src/com/intellij/openapi/options/colors/pages/PropertiesColorsPage.java) -for -[Properties language plugin](upsource:///plugins/properties/) +- [`ColorSettingsPage`](upsource:///plugins/properties/src/com/intellij/openapi/options/colors/pages/PropertiesColorsPage.java) for [Properties language plugin](upsource:///plugins/properties/) - [Custom Language Support Tutorial: Color Settings Page](/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md) diff --git a/reference_guide/editors.md b/reference_guide/editors.md index 3fba5dfdf..718f76b43 100644 --- a/reference_guide/editors.md +++ b/reference_guide/editors.md @@ -3,13 +3,12 @@ title: Editors --- -This section covers working with text in the IntelliJ Platform editor. +This section covers working with text in the IntelliJ Platform editor. It is presented in two major sections: * [Editor basics tutorial](/tutorials/editor_basics.md) * Using the action system to access a caret placed in a document open in an editor. - * Accessing position information about a caret in an editor: coordinate systems and offsets. - * Handling actions activated by keystroke events in the editor. + * Accessing position information about a caret in an editor: coordinate systems and offsets. + * Handling actions activated by keystroke events in the editor. * [Multiple carets](multiple_carets.md) * Working with multiple, independent, carets in one editor. - * How multiple carets affect core functionality, editor actions, typing actions, and code insight actions. - \ No newline at end of file + * How multiple carets affect core functionality, editor actions, typing actions, and code insight actions. diff --git a/reference_guide/frameworks_and_external_apis/external_builder_api.md b/reference_guide/frameworks_and_external_apis/external_builder_api.md index 05ff8451a..c331db704 100644 --- a/reference_guide/frameworks_and_external_apis/external_builder_api.md +++ b/reference_guide/frameworks_and_external_apis/external_builder_api.md @@ -3,61 +3,65 @@ title: External Builder API and Plugins --- -> **NOTE** Adding JPS support to your plugin requires Java plugin to be present for it to work. Please see [Plugin Dependencies](/basics/plugin_structure/plugin_dependencies.md) on how to setup your plugin with required dependency. +> **NOTE** Adding JPS support to your plugin requires Java plugin to be present for it to work. +> Please see [Plugin Dependencies](/basics/plugin_structure/plugin_dependencies.md) on how to set up your plugin with required dependency. ### External Build Process Workflow When the user invokes an action that involves executing an external build (Make, Build Artifacts, etc.), the following steps happen: -* Before-compile tasks are executed in the IDE process. - -* Some source generation tasks that depend on the PSI (e.g. UI designer form to source compilation) are executed in the IDE process. - -* [`BuildTargetScopeProvider`](upsource:///java/compiler/impl/src/com/intellij/compiler/impl/BuildTargetScopeProvider.java) extensions are called to calculate the scope of the external build (the set of build targets to compile based on the target module to make and the known set of changes). - -* The external build process is spawned (or an existing build process background process is reused). - -* The external build process loads the project model (.idea, .iml files and so on), represented by a [`JpsModel`](upsource:///jps/model-api/src/org/jetbrains/jps/model/JpsModel.java) instance. - -* The full tree of targets to build is calculated, based on the dependencies of each build target to be compiled. - -* For each target, the set of builders capable of building this target is calculated. - -* For every target and every builder, the `build()` method is called. This can happen in parallel if the "Compile independent modules in parallel" option is enabled in the settings. For module-level builders, the order of invoking builders for a single target is determined by their category; for other builders, the order is undefined. - -* Caches to record the state of the compilation are saved. - -* Compilation messages reported through the [`CompileContext`](upsource:///jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java) API are transmitted to the IDE process and displayed in the UI (in the *Messages* view). - -* Post-compile tasks are executed in the IDE process. +* Before-compile tasks are performed in the IDE process. +* Some source generation tasks that depend on the PSI (e.g., UI designer form to source compilation) are executed in the IDE process. +* [`BuildTargetScopeProvider`](upsource:///java/compiler/impl/src/com/intellij/compiler/impl/BuildTargetScopeProvider.java) extensions are called to calculate the scope of the external build (the set of build targets to compile based on the target module to make and the known set of changes). +* The external build process is spawned (or an existing build process background process is reused). +* The external build process loads the project model (.idea, .iml files, and so on), represented by a [`JpsModel`](upsource:///jps/model-api/src/org/jetbrains/jps/model/JpsModel.java) instance. +* The full tree of targets to build is calculated based on each build target's dependencies to be compiled. +* For each target, the set of builders capable of building this target is calculated. +* For every target and every builder, the `build()` method is called. + This can happen in parallel if the "Compile independent modules in parallel" option is enabled in the settings. + For module-level builders, the order of invoking builders for a single target is determined by their category; for other builders, the order is undefined. +* Caches to record the state of the compilation are saved. +* Compilation messages reported through the [`CompileContext`](upsource:///jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java) API are transmitted to the IDE process and displayed in the UI (in the *Messages* view). +* Post-compile tasks are executed in the IDE process. ### Incremental Build -To support incremental build, the build process uses a number of caches which are persisted between build invocations. Even if your compiler doesn't support incremental build, you still need to report correct information so that incremental build works correctly for other compilers. +To support incremental build, the build process uses several caches which are persisted between build invocations. +Even if your compiler doesn't support incremental build, you still need to report correct information so that incremental build works correctly for other compilers. -* [`SourceToOutputMapping`](upsource:///jps/jps-builders/src/org/jetbrains/jps/builders/storage/SourceToOutputMapping.java) is a many-to-many relationship between source files and output files ("which source files were used to produce the specified output file"). It's filled by calls to `BuildOutputConsumer.registerOutputFile()` and `ModuleLevelBuilder.OutputConsumer.registerOutputFile()`. +* [`SourceToOutputMapping`](upsource:///jps/jps-builders/src/org/jetbrains/jps/builders/storage/SourceToOutputMapping.java) is a many-to-many relationship between source files and output files ("which source files were used to produce the specified output file"). + It's filled by calls to `BuildOutputConsumer.registerOutputFile()` and `ModuleLevelBuilder.OutputConsumer.registerOutputFile()`. -The IDE monitors the changes of the project content and uses the information from those caches to generate the set of dirty and deleted files for every compilation. (Dirty files need to be recompiled, and deleted files need to have their output deleted). A builder can also report additional files as dirty (e.g. if a method is deleted, the builder can report the classes using this method as dirty.) A module-level builder can add some files to the dirty scope; if this happens, and if the builder returns `ADDITIONAL_PASS_REQUIRED` from its `build()` method, another round of builder execution for the same module chunk will be started with the new dirty scope. +The IDE monitors the project content changes and uses the information from those caches to generate the set of dirty and deleted files for every compilation. (Dirty files need to be recompiled, and deleted files need to have their output deleted). +A builder can also report additional files as dirty (e.g., if a method is deleted, the builder can report the classes using this method as dirty.) A module-level builder can add some files to the dirty scope; if this happens, and if the builder returns `ADDITIONAL_PASS_REQUIRED` from its `build()` method, another round of builder execution for the same module chunk will be started with the new dirty scope. -A builder may also want to have its custom caches to store additional information to support partial recompilation of a target (e.g. the dependencies between Java files in a module). To store this data, you can either store arbitrary files in the directory returned from `BuildDataManager.getDataPaths().getTargetDataRoot()` or use a higher-level API: `BuildDataManager.getStorage()` +A builder may also want to have its custom caches to store additional information to support the partial recompilation of a target (e.g., the dependencies between Java files in a module). +To store this data, you can either store arbitrary files in the directory returned from `BuildDataManager.getDataPaths().getTargetDataRoot()` or use a higher-level API: `BuildDataManager.getStorage()` To pass custom data between the invocation of the same builder between multiple targets, you can use `CompileContext.getUserData()` and `CompileContext.putUserData()`. ### Services and Extensions in External Builder -The external builder process uses the standard Java -[services](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) -mechanism to support plugins. There are several service interfaces (e.g. [`BuilderService`](upsource:///jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java) which can be implemented in plugins to extend the builder functionality. An implementation of a service need to be registered by creating `META-INF/services/` file containing the qualified name of the implementation class. E.g. `BuilderService` implementations are registered in `META-INF/services/org.jetbrains.jps.incremental.BuilderService` file. These files don't have extensions so you need to map corresponding patterns to text files in IDE settings. +The external builder process uses the standard Java [services](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) mechanism to support plugins. +There are several service interfaces (e.g. [`BuilderService`](upsource:///jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java) which can be implemented in plugins to extend the builder functionality. +An implementation of a service needs to be registered by creating the `META-INF/services/` file containing the implementation class's qualified name. +E.g. `BuilderService` implementations are registered in `META-INF/services/org.jetbrains.jps.incremental.BuilderService` file. +These files don't have extensions, so you need to map corresponding patterns to text files in IDE settings. ### Registering a Plugin for External Builder -Sources of a plugin for External Builder should be put in a separate module. By convention such module has name '...-jps-plugin' and its sources are placed under 'jps-plugin' directory in the main plugin directory. Use `com.intellij.compileServer.plugin` extension to add the plugin to classpath of external build process, the plugin jar should be named `.jar`. 'Build' \| 'Prepare Plugin Module for deployment' action will automatically pack 'jps-plugin' part to a separate jar accordingly. +Sources of a plugin for External Builder should be put in a separate module. +By convention, such a module has a name '...-jps-plugin', and its sources are placed under the 'jps-plugin' directory in the main plugin directory. +Use `com.intellij.compileServer.plugin` extension to add the plugin to the classpath of the external build process, the plugin jar should be named `.jar`. 'Build' \| 'Prepare Plugin Module for deployment' action will automatically pack the 'jps-plugin' part to a separate jar accordingly. ### Debugging a Plugin for External Builder **If your test IDE is IntelliJ IDEA 16.0 or newer** -Switch on "Debug Build Process" toggle action (available via 'Find Action') in the test IDE. After that every time compilation is run, the build process will wait for debugger connection on some (random) port and will show the port number in the status bar. In working copy of IDE a "Remote" run configuration should be created and pointed to this port. If you often need to debug external builders and want to reuse the created "Remote" run configuration you may fix the port number by adding the following VM option to the plugin run configuration: +Switch on "Debug Build Process" toggle action (available via 'Find Action') in the test IDE. +After that every time compilation is run, the build process will wait for debugger connection on some (random) port and will show the port number in the status bar. +In a working copy of IDE, a "Remote" run configuration should be created and pointed to this port. +Suppose you often need to debug external builders and want to reuse the created "Remote" run configuration. In that case, you may fix the port number by adding the following VM option to the plugin run configuration: ``` -Dcompiler.process.debug.port= @@ -66,61 +70,58 @@ Switch on "Debug Build Process" toggle action (available via 'Find Action') in t **If your test IDE is IntelliJ IDEA 15.0 or older** -Start IDE with your plugin with the following VM option +Start IDE with your plugin with the following VM option: ``` -Dcompiler.process.debug.port= ``` -After that every time compilation is run in the test IDE, the build process will wait for debugger connection on this port and only then proceed. In working copy of IDE a "Remote" run configuration should be created and pointed to this port. Specifying port "-1" will disable debugging mode. +After that, every time compilation is run in the test IDE, the build process will wait for debugger connection on this port and then proceed. In a working copy of IDE, a "Remote" run configuration should be created and pointed to this port. +Specifying port "-1" will disable debugging mode. ### Profiling External Build Process -The build process has built-in self-cpu-profiling capabilities. To enable them do the following: +The build process has built-in self-cpu-profiling capabilities. +To enable them do the following: 1. Copy `/lib/yjp-controller-api-redist.jar` and `/bin/yjpagent.*` files to `/compile-server` - 2. In "Settings \| Compiler \| Additional compiler process VM options" field enter `-Dprofiling.mode=true` - 3. Make sure automatic make is turned off -After this every build process run should result in a CPU snapshot stored in ``/Snapshots directory. +After this, every build process run should result in a CPU snapshot stored in ``/Snapshots directory. Snapshots are named like "ExternalBuild\-\{date\}.snapshot". Specifying `-Dprofiling.mode=false` will turn profiling off. -Please capture a couple of snapshots for the situations in which you believe the build should work much faster than it does. +Please capture a couple of snapshots for the situations you believe the build should work much faster than it does. -Please create an issue in the issue tracker and attach generated \*.snapshot files to it or upload them -as [described here](https://intellij-support.jetbrains.com/hc/en-us/articles/206869619) and specify links in the issue. +Please create an issue in the issue tracker and attach generated \*.snapshot files to it or upload them as [described here](https://intellij-support.jetbrains.com/hc/en-us/articles/206869619) and specify links in the issue. Please also provide details about the memory and other VM settings for the build process you were using. ### Accessing External Build Process' Logs -The log file is located under the directory +The log file is located under the directory: ``` /log/build-log ``` -There both `build-log.log` and `build-log.properties` files can be found. -The `build-log.properties` is a log4j configuration file, where the log level and desired logging categories can be adjusted. -This file contains logging from all build sessions, including those from the auto-make. +There, both `build-log.log` and `build-log.properties` files can be found. +The `build-log.properties` is a log4j configuration file, where the log level and desired logging categories can be adjusted. +This file contains logging from all build sessions, including those from the auto-make. -In IntelliJ Platform versions before version 14.1 log4j configuration was stored in `build-log.xml`. +In IntelliJ Platform versions before version 14.1, log4j configuration was stored in `build-log.xml`. ### Accessing Project Model and Configuration from External Build -The project model in External Build process is provided by JPS (*JetBrains Project System*). -A project is represented by [`JpsProject`](upsource:///jps/model-api/src/org/jetbrains/jps/model/JpsProject.java), a module by [`JpsModule`](upsource:///jps/model-api/src/org/jetbrains/jps/model/JpsProject.java) and so on. -If your compiler depends on something that isn't added to the model yet (e.g. some facet settings), -you need to extend the JPS model (use `JpsOsmorcModuleExtension` as a reference implementation) and provide implementation of -[`JpsModelSerializerExtension`](upsource:///jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelSerializerExtension.java) to load the configuration from project files. +The project model in the External Build process is provided by JPS (*JetBrains Project System*). +A project is represented by [`JpsProject`](upsource:///jps/model-api/src/org/jetbrains/jps/model/JpsProject.java), a module by [`JpsModule`](upsource:///jps/model-api/src/org/jetbrains/jps/model/JpsProject.java), and so on. +Suppose your compiler depends on something that isn't added to the model yet (e.g., some facet settings). +In that case, you need to extend the JPS model (use `JpsOsmorcModuleExtension` as a reference implementation) and provide an implementation of [`JpsModelSerializerExtension`](upsource:///jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsModelSerializerExtension.java) to load the configuration from project files. #### Implementing Builder -If your compiler isn't involved into compilation of an existing [`BuildTarget`](upsource:///jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java) you need to create a new implementation of `BuildTarget` and `BuildTargetType`. Also register an implementation of [`BuildTargetScopeProvider`](upsource:///java/compiler/impl/src/com/intellij/compiler/impl/BuildTargetScopeProvider.java) extension on IDE side to add required targets to the build scope. +If your compiler isn't involved in the compilation of an existing [`BuildTarget`](upsource:///jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java), you need to create a new implementation of `BuildTarget` and `BuildTargetType`. +Also, register an implementation of [`BuildTargetScopeProvider`](upsource:///java/compiler/impl/src/com/intellij/compiler/impl/BuildTargetScopeProvider.java) extension on the IDE side to add required targets to the build scope. The builder implementation should extend either [`TargetBuilder`](upsource:///jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java) or [`ModuleLevelBuilder`](upsource:///jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java) class and should be created using [`BuilderService`](upsource:///jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java) extension. - - diff --git a/reference_guide/frameworks_and_external_apis/external_system_integration.md b/reference_guide/frameworks_and_external_apis/external_system_integration.md index 36d4f5faf..4f17ff9d4 100644 --- a/reference_guide/frameworks_and_external_apis/external_system_integration.md +++ b/reference_guide/frameworks_and_external_apis/external_system_integration.md @@ -4,11 +4,12 @@ title: External System Integration This page provides high-level overview of *External System* sub-system. -There are multiple project management systems ([Apache Maven](https://maven.apache.org/), [Gradle](https://www.gradle.org/), [sbt](https://www.scala-sbt.org/) etc) and it's good to support them at the IDE. Luckily, they all provide a similar set of facilities from the integration point of view: -* build IDE project from external system config (`pom.xml`, `build.gradle` etc); -* provide a list of available tasks; -* allow to execute a particular task; -* ... +There are multiple project management systems ([Apache Maven](https://maven.apache.org/), [Gradle](https://www.gradle.org/), [sbt](https://www.scala-sbt.org/) etc) and it's good to support them at the IDE. +Luckily, they all provide a similar set of facilities from the integration point of view: +* build IDE project from external system config (`pom.xml`, `build.gradle` etc); +* provide a list of available tasks; +* allow to execute a particular task; +* ... That means that we can separate external system-specific logic and general IDE processing. *'External system'* sub-system provides simple API for wrapping external system and extensible IDE-specific processing logic. @@ -16,32 +17,41 @@ That means that we can separate external system-specific logic and general IDE p ### Project Data Domain -**General** -External system wrapper is required to be able to build project info on the basis of the given external system config. That information is built using in terms of [`DataNode`](upsource:///platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java), [`Key`](upsource:///platform/external-system-api/src/com/intellij/openapi/externalSystem/model/Key.java) and [`ExternalEntityData`](upsource:///platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalEntityData.java). +**General** +External system wrapper is required to be able to build project info on the basis of the given external system config. +That information is built using in terms of [`DataNode`](upsource:///platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java), [`Key`](upsource:///platform/external-system-api/src/com/intellij/openapi/externalSystem/model/Key.java) and [`ExternalEntityData`](upsource:///platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalEntityData.java). ![DataNode](/reference_guide/img/data-node.png) -Here *DataNode* class is just a holder for the target data (data type is defined by the *Key*). Multiple DataNode objects might be organized in directed graph where every edge identifies parent-child relation. +Here *DataNode* class is just a holder for the target data (data type is defined by the *Key*). +Multiple DataNode objects might be organized in directed graph where every edge identifies parent-child relation. + +For example, simple one-module project might look as below: -For example, simple one-module project might look as below: - ![DataNode Example](/reference_guide/img/data-node-example.png) -**Consequence** +**Consequence** The IDE provides a set of built-in *Key*s and *ExternalEntityData*s but any external system integration or third-party plugin developer might enhance project data by defining her own *Key* and *ExternalEntityData* and storing them at a child of appropriate *DataNode*. ### Managing Project Data -We need to process project data is built on external system config basis. Here comes [`ProjectDataService`](upsource:///platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataService.java). It is a strategy which knows how to manage particular *ExternalEntityData*. For example, when we want to import a project from external model, we can start by the top level *DataNode* which references project info and then import its data using corresponding service. +We need to process project data is built on external system config basis. +Here comes [`ProjectDataService`](upsource:///platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataService.java). +It is a strategy which knows how to manage particular *ExternalEntityData*. +For example, when we want to import a project from external model, we can start by the top level *DataNode* which references project info and then import its data using corresponding service. Custom services can be defined via *'externalProjectDataService'* extension. -The good thing is that we can separate project parsing and management here. That means that a set of *DataNode*, *Key* and *ProjectDataServices* can be introduced for particular technology and then every external system integration can build corresponding data if necessary using it. +The good thing is that we can separate project parsing and management here. +That means that a set of *DataNode*, *Key* and *ProjectDataServices* can be introduced for particular technology and then every external system integration can build corresponding data if necessary using it. ### Importing from External Model -IntelliJ platform provides standard API for that. Namely, [`ProjectImportBuilder`](upsource:///java/idea-ui/src/com/intellij/projectImport/ProjectImportBuilder.java) and [`ProjectImportProvider`](upsource:///java/idea-ui/src/com/intellij/projectImport/ProjectImportProvider.java). There are two classes built on *template method* pattern - [`AbstractExternalProjectImportBuilder`](upsource:///java/idea-ui/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java) and [`AbstractExternalProjectImportProvider`](upsource:///java/idea-ui/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportProvider.java). Concrete implementations are registered in `plugin.xml`. +IntelliJ platform provides standard API for that. +Namely, [`ProjectImportBuilder`](upsource:///java/idea-ui/src/com/intellij/projectImport/ProjectImportBuilder.java) and [`ProjectImportProvider`](upsource:///java/idea-ui/src/com/intellij/projectImport/ProjectImportProvider.java). +There are two classes built on *template method* pattern - [`AbstractExternalProjectImportBuilder`](upsource:///java/idea-ui/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java) and [`AbstractExternalProjectImportProvider`](upsource:///java/idea-ui/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportProvider.java). +Concrete implementations are registered in `plugin.xml`. Here is an example from the gradle integration plugin: @@ -60,23 +70,30 @@ It's possible to configure external system integration to automatically refresh Describe project's settings files to track by having external system `ExternalSystemManager` implement [`ExternalSystemAutoImportAware`](upsource:///platform/external-system-api/src/com/intellij/openapi/externalSystem/ExternalSystemAutoImportAware.java). -> **NOTE** `ExternalSystemAutoImportAware.getAffectedExternalProjectPath()` is called quite often, that’s why it’s expected to return control as soon as possible. Helper `CachingExternalSystemAutoImportAware` class might be used for caching, i.e. `ExternalSystemManager` which implements `ExternalSystemAutoImportAware` can have a field like `new CachingExternalSystemAutoImportAware(new MyExternalSystemAutoImportAware())` and delegate `ExternalSystemAutoImportAware.getAffectedExternalProjectPath()` calls to it. +> **NOTE** `ExternalSystemAutoImportAware.getAffectedExternalProjectPath()` is called quite often, that’s why it’s expected to return control as soon as possible. +> Helper `CachingExternalSystemAutoImportAware` class might be used for caching, i.e. `ExternalSystemManager` which implements `ExternalSystemAutoImportAware` can have a field like `new CachingExternalSystemAutoImportAware(new MyExternalSystemAutoImportAware())` and delegate `ExternalSystemAutoImportAware.getAffectedExternalProjectPath()` calls to it. ### Auto-Import for Standalone External Systems -Some external systems don’t have `ExternalSystemManager` (e.g., Maven), but they also can use auto-import core to track changes in settings files. For this, implement `ExternalSystemProjectAware` interface that describes settings files for tracking and an action to reload project model. -Then register the instance with `ExternalSystemProjectTracker` to start tracking. +Some external systems don’t have `ExternalSystemManager` (e.g., Maven), but they also can use auto-import core to track changes in settings files. +For this, implement `ExternalSystemProjectAware` interface that describes settings files for tracking and an action to reload project model. +Then register the instance with `ExternalSystemProjectTracker` to start tracking. -> **NOTE** Multiple `ExternalSystemProjectAware` instances can correspond to a single external system. It allows performing project reload differently depending on the set of settings files (project aware per settings file, per module, per external project, etc.). +> **NOTE** Multiple `ExternalSystemProjectAware` instances can correspond to a single external system. +> It allows performing project reload differently depending on the set of settings files (project aware per settings file, per module, per external project, etc.). ### Icon for Reload Notification -Since 2020.1, the icon for reload notification can be specified per external system. Implement `ExternalSystemIconProvider` and register via `com.intellij.externalIconProvider` extension point in `plugin.xml`. Alternatively, set `reloadIcon` field external system implements `ExternalSystemIconProvider` directly. +Since 2020.1, the icon for reload notification can be specified per external system. +Implement `ExternalSystemIconProvider` and register via `com.intellij.externalIconProvider` extension point in `plugin.xml`. +Alternatively, set `reloadIcon` field external system implements `ExternalSystemIconProvider` directly. ## Settings -The general idea is that all external system settings controls are represented by implementations of [`ExternalSystemSettingsControl`](upsource:///platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemSettingsControl.java) interface. There are also external system project-local settings and global external system settings. So, basically particular external system settings UI looks as below: +The general idea is that all external system settings controls are represented by implementations of [`ExternalSystemSettingsControl`](upsource:///platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemSettingsControl.java) interface. +There are also external system project-local settings and global external system settings. +So, basically particular external system settings UI looks as below: ![Configurable](/reference_guide/img/configurable.png) diff --git a/reference_guide/frameworks_and_external_apis/spring_api.md b/reference_guide/frameworks_and_external_apis/spring_api.md index d327fa246..8bc71f0c1 100644 --- a/reference_guide/frameworks_and_external_apis/spring_api.md +++ b/reference_guide/frameworks_and_external_apis/spring_api.md @@ -7,50 +7,54 @@ Spring API allows 3rd party plugins to re-use, integrate with or extend existing A popular plugin using Spring API is [hybris integration](https://plugins.jetbrains.com/plugin/7525-hybris-integration). -To develop plugins you will need to use _IntelliJ IDEA Ultimate Edition_ version 13.1 or higher. +To develop plugins, you will need to use _IntelliJ IDEA Ultimate Edition_ version 13.1 or higher. ## Setting up IntelliJ Platform SDK -> **NOTE** This applies to [Plugin DevKit](/basics/getting_started/using_dev_kit.md) projects only. For [Gradle](/tutorials/build_system.md) projects, simply add dependency to bundled Spring plugin `com.intellij.spring`. +> **NOTE** This applies to [Plugin DevKit](/basics/getting_started/using_dev_kit.md) projects only. +> For [Gradle](/tutorials/build_system.md) projects, simply add dependency to bundled Spring plugin `com.intellij.spring`. ### New SDK Please create an IntelliJ Platform SDK to include all minimum required files. Then add `$IDEA_HOME$/plugins/Spring/lib/spring.jar` to its _classpath_ (_not_ to your plugin module's dependencies). ### Existing SDK -Follow these steps to modify existing IntelliJ Platform SDK: +Follow these steps to modify the existing IntelliJ Platform SDK: * add to _classpath_ (_not_ to your plugin module's dependencies) - * `$IDEA_HOME$/plugins/Spring/lib/spring-api.jar` _not in recent versions, merged into `spring.jar`_ - * `$IDEA_HOME$/plugins/Spring/lib/spring.jar` + * `$IDEA_HOME$/plugins/Spring/lib/spring-api.jar` _not in recent versions, merged into `spring.jar`_ + * `$IDEA_HOME$/plugins/Spring/lib/spring.jar` * add to _sourcepath_ - * `$IDEA_HOME$/lib/src/src_spring-openapi.zip` + * `$IDEA_HOME$/lib/src/src_spring-openapi.zip` ### General Notes -If you use other Spring functionality (e.g. Spring EL) in your plugin, make sure to add all required JARs to your IntelliJ Platform SDK classpath to make your plugin's tests work. +If you use other Spring functionality (e.g., Spring EL) in your plugin, add all required JARs to your IntelliJ Platform SDK classpath to make your plugin's tests work. - -Please use only Spring-related functionality exposed in `spring-api.jar` (where sources are provided) in your plugin. Using any other "internal" (implementation) classes from Spring plugin itself (`spring.jar`) is _not_ supported. +Please use only Spring-related functionality exposed in `spring-api.jar` (where sources are provided) in your plugin. +Using any other "internal" (implementation) classes from Spring plugin itself (`spring.jar`) is _not_ supported. ### plugin.xml -Add `com.intellij.spring` to your `plugin.xml` to require "Spring Support" plugin to be activated. All available extension points are provided under `com.intellij.spring` prefix. -Note that "Spring Support" plugin itself has dependencies to a few other plugins which need to be enabled in your sandbox (see notifications on startup). +Add `com.intellij.spring` to your `plugin.xml` to require "Spring Support" plugin to be activated. +All available extension points are provided under `com.intellij.spring` prefix. +Note that the "Spring Support" plugin itself has dependencies on a few other plugins which need to be enabled in your sandbox (see notifications on startup). ## Main Concepts -A Spring facet can be attached on a Module. (Nearly) All Spring functionality requires an existing and properly setup Spring facet. +A Spring facet can be attached to a Module. +Nearly all Spring functionality requires an existing and correctly setup Spring facet. -Spring facets usually contain one more user-configured or automatically provided filesets, which group a set of Spring related configuration files (XML, Code, .properties or other configuration files). +Spring facets usually contain one more user-configured or automatically provided filesets, which group a set of Spring related configuration files (XML, Code, .properties, or other configuration files). -A fileset usually corresponds to an actual application context configuration at runtime. Hierarchies can be modeled by depending on another fileset (possibly from another module). +A fileset usually corresponds to an actual application context configuration at runtime. +Hierarchies can be modeled by depending on another fileset (possibly from another module). -As an API-user, you will usually rather work with `SpringModel` (which is built on top of fileset(s)). +As an API-user, you will usually prefer working with `SpringModel`, which is built on top of fileset(s). ## API Updates > **NOTE** 2017.3: `LocalXmlModel#setActiveProfiles` & `LocalAnnotationModel#setActiveProfiles` have been deprecated and will be removed in 2018.1. -> **NOTE** Starting with 2016.2, internal representation of bean _type_ has been changed from `PsiClass` to `PsiType`, please note deprecations. +> **NOTE** Starting with 2016.2, the internal representation of bean _type_ has been changed from `PsiClass` to `PsiType`, please note deprecations. -> **NOTE** Some core classes have been changed in 14(.1), please see "_Version 14(.1)_" notes for info on how to replace existing API-calls. +> **NOTE** Some core classes have been changed in 14(.1); please see "_Version 14(.1)_" notes for info on how to replace existing API-calls. ## How Do I... @@ -68,7 +72,8 @@ See `SpringManager#getSpringModel(s)...` and `com.intellij.spring.model.utils.Sp See `com.intellij.spring.SpringModelProvider` to provide implicit filesets (e.g. provided by another framework in a specific configuration file). _Version 15_ -See `com.intellij.spring.facet.SpringAutodetectedFileSet` for a convenient base class. Please note that autodetected filesets cannot be edited/modified by users in Spring facet. +See `com.intellij.spring.facet.SpringAutodetectedFileSet` for a convenient base class. +Please note that autodetected filesets cannot be edited/modified by users in Spring facet. #### Customize Implicit Models Configuration _2017.1_ See `com.intellij.spring.facet.SpringFileSetEditorCustomization` to customize presentation and/or add extra settings/actions for specific autodetected filesets. @@ -105,7 +110,7 @@ _Version 16_: note deprecation of `SpringModelSearchParameters.BeanClass#withInh _Version 14_: `com.intellij.spring.model.utils.SpringModelSearchers#doesBeanExist` (please note deprecated methods) #### Mark Bean as Infrastructure Bean -_Version 14_: implement `SpringInfrastructureBean`, such beans obtain special icon and can be filtered in various places in UI. +_Version 14_: implement `SpringInfrastructureBean`, such beans obtain a special icon and can be filtered in various places in UI. ### XML Configuration All support for XML-based Spring configuration files is provided via [DOM-API](xml_dom_api.md). @@ -158,39 +163,41 @@ Additional files to be processed by inspections registered with Spring Validator Use `com.intellij.spring.facet.SpringConfigurator` to provide "automatic" configuration when Spring facet is added via framework wizard. #### UI/Presentation -Please do not reference bean icons from `SpringApiIcons` directly, but use `SpringPresentationProvider` to re-use unified icon/bean name. See `SpringBeansPsiElementCellRenderer` for popup/list renderer. +Please do not reference bean icons from `SpringApiIcons` directly, but use `SpringPresentationProvider` to re-use unified icon/bean name. +See `SpringBeansPsiElementCellRenderer` for popup/list renderer. ## Spring Boot _2018.1_ -Spring Boot API allows to extend/access Spring Boot specific support in the IDE. +Spring Boot API allows extending/accessing Spring Boot specific support in the IDE. -> **WARNING** While we try to maintain compatibility, please be prepared for a less strict policy. +> **WARNING** While we try to maintain compatibility, please be prepared for a less strict policy. ### Setting up Please perform these steps _additionally_ to setting up Spring API support (see [here](#setting-up-intellij-platform-sdk)): * add to _classpath_ (_not_ to your plugin module's dependencies) - * `$IDEA_HOME$/plugins/SpringBoot/lib/spring-boot.jar` - * `$IDEA_HOME$/plugins/SpringBoot/lib/spring-boot-initializr.jar` (optional) - * `$IDEA_HOME$/plugins/SpringBoot/lib/spring-boot-run.jar` (optional) + * `$IDEA_HOME$/plugins/SpringBoot/lib/spring-boot.jar` + * `$IDEA_HOME$/plugins/SpringBoot/lib/spring-boot-initializr.jar` (optional) + * `$IDEA_HOME$/plugins/SpringBoot/lib/spring-boot-run.jar` (optional) * add to _sourcepath_ - * `$IDEA_HOME$/lib/src/src_spring-boot-openapi.zip` + * `$IDEA_HOME$/lib/src/src_spring-boot-openapi.zip` ### plugin.xml -Add `com.intellij.spring.boot` to your `plugin.xml` to require "Spring Boot" plugin to be activated. All available extension points are provided under `com.intellij.spring.boot` prefix. +Add `com.intellij.spring.boot` to your `plugin.xml` to require "Spring Boot" plugin to be activated. +All available extension points are provided under `com.intellij.spring.boot` prefix. ### Spring Boot Library Use `com.intellij.spring.boot.library.SpringBootLibraryUtil` to query version and availability of common additional libraries. ### Custom Configuration Files Format -`com.intellij.spring.boot.model.SpringBootModelConfigFileContributor` allows adding support for custom config file formats. - +`com.intellij.spring.boot.model.SpringBootModelConfigFileContributor` allows adding support for custom config file formats. + ### Auto-Configuration Support Existing `Condition` implementations can be simulated at design time in IDE via `com.intellij.spring.boot.model.autoconfigure.conditions.ConditionalContributor`. -Custom `@ConditionalOn...` annotations implementing `com.intellij.spring.boot.model.autoconfigure.conditions.jam.ConditionalOnJamElement` will be added into evaluation automatically. +Custom `@ConditionalOn...` annotations implementing `com.intellij.spring.boot.model.autoconfigure.conditions.jam.ConditionalOnJamElement` will be added into evaluation automatically. ### Spring Initializr requires `spring-boot-initializr.jar` @@ -200,4 +207,5 @@ requires `spring-boot-initializr.jar` ### Endpoint Tab _2018.2_ - requires `spring-boot-run.jar` -Use EP `com.intellij.spring.boot.run.endpoint` to add custom actuator endpoint tabs. Any settings should be exposed in "Spring Boot" settings tab via `com.intellij.spring.boot.run.endpointTabConfigurable` EP. +Use EP `com.intellij.spring.boot.run.endpoint` to add custom actuator endpoint tabs. +Any settings should be exposed in "Spring Boot" settings tab via `com.intellij.spring.boot.run.endpointTabConfigurable` EP. diff --git a/reference_guide/frameworks_and_external_apis/xml_dom_api.md b/reference_guide/frameworks_and_external_apis/xml_dom_api.md index 53bd33bf4..948bea2cc 100644 --- a/reference_guide/frameworks_and_external_apis/xml_dom_api.md +++ b/reference_guide/frameworks_and_external_apis/xml_dom_api.md @@ -7,14 +7,18 @@ title: XML DOM API ## Abstract -This article is intended for plugin writers who create custom web server integrations, or some UI for easy XML editing. It describes the *Document Object Model* (DOM) in IntelliJ Platform --- an easy way to work with DTD or Schema-based XML models. +This article is intended for plugin writers who create custom web server integrations, or some UI for easy XML editing. +It describes the *Document Object Model* (DOM) in IntelliJ Platform --- an easy way to work with DTD or Schema-based XML models. The following topics will be covered: working with DOM itself (reading/writing tags content, attributes, and subtags) and easy XML editing in the UI by connecting UI to DOM. It's assumed that the reader is familiar with Java, Swing, IntelliJ Platform XML PSI (classes [`XmlTag`](upsource:///xml/xml-psi-api/src/com/intellij/psi/xml/XmlTag.java), [`XmlFile`](upsource:///xml/xml-psi-api/src/com/intellij/psi/xml/XmlFile.java), [`XmlTagValue`](upsource:///xml/xml-psi-api/src/com/intellij/psi/xml/XmlTagValue.java), etc.), IntelliJ Platform plugin development basics (application and project components, file editors). ## Introduction -So, how to operate with XML from an IntelliJ Platform plugin? Usually, one has to take `XmlFile`, get its root tag, and then find a required sub-tag by path. The path consists of tag names, each of them a string. Typing these everywhere is tedious and error-prone. Let's assume you have the following XML: +So, how to operate with XML from an IntelliJ Platform plugin? Usually, one has to take `XmlFile`, get its root tag, and then find a required sub-tag by path. +The path consists of tag names, each of them a string. +Typing these everywhere is tedious and error-prone. +Let's assume you have the following XML: ```xml @@ -36,8 +40,8 @@ findSubTags("bar")[1].getValue().getTrimmedText() because each call here may return `null`. -So the code would probably look like this: - +So the code would probably look like this: + ```java XmlFile file = ...; final XmlDocument document = file.getDocument(); @@ -56,7 +60,8 @@ if (document != null) { } ``` -Looks awful, doesn't it? But there's a better way to do the same thing. You just need to extend a special interface --- [`DomElement`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/DomElement.java). +Looks awful, doesn't it? But there's a better way to do the same thing. +You just need to extend a special interface --- [`DomElement`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/DomElement.java). For example, let's create several interfaces: @@ -78,7 +83,8 @@ Next, you should create a [`DomFileDescription`](upsource:///xml/dom-openapi/src > **NOTE** If your plugin targets 2019.1 or later, please use extension point `com.intellij.dom.fileMetaData` instead and specify `rootTagName` and `domVersion`/`stubVersion` in `plugin.xml`. -You can now get the file element from [`DomManager`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/DomManager.java). To get the "239" value, you only have to write the following code: +You can now get the file element from [`DomManager`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/DomManager.java). +To get the "239" value, you only have to write the following code: ```java DomManager manager = DomManager.getDomManager(project); @@ -90,25 +96,38 @@ if (bars.size() > 1) { } ``` -I suppose this looks a little bit nicer. You often work with your model in more than one place. Re-creating the model is too inefficient, so we cache it for you, and any subsequent calls to `DomManager.getFileElement()` will return the same instance. So, it is useful to invoke this method just once, and then keep everywhere only the "root" object you've obtained. In this case you wont need to repeat that scary first line, and the code will look even nicer. +I suppose this looks a little bit nicer. +You often work with your model in more than one place. +Re-creating the model is too inefficient, so we cache it for you, and any subsequent calls to `DomManager.getFileElement()` will return the same instance. +So, it is useful to invoke this method just once, and then keep everywhere only the "root" object you've obtained. +In this case you wont need to repeat that scary first line, and the code will look even nicer. -It is also important to note that with this scenario we avoid potential `NullPointerException`: our DOM guarantees that every method accessing a tags child will return a not-null element, even if the correspondingly-named sub-tag doesn't exist. That may seem strange at a first glance, but it appears to be rather convenient. How does it work? Simple. Given those interfaces, DOM generates all code for accessing correct sub-tags and creating model elements at runtime. The sub-tag names and element types are taken from method names, return types and method annotations, if any. In most cases annotations can be omitted, as in our example, but this is discussed further in this article anyway. +It is also important to note that with this scenario we avoid potential `NullPointerException`: our DOM guarantees that every method accessing a tags child will return a not-null element, even if the correspondingly-named sub-tag doesn't exist. +That may seem strange at a first glance, but it appears to be rather convenient. +How does it work? Simple. +Given those interfaces, DOM generates all code for accessing correct sub-tags and creating model elements at runtime. +The sub-tag names and element types are taken from method names, return types and method annotations, if any. +In most cases annotations can be omitted, as in our example, but this is discussed further in this article anyway. -Now let us explore more thoroughly what the DOM can do, and look at possible ways of representing various XML concepts such as tag content, attributes or sub-tags. Later we will discuss basic methods for working with the model, as well as cover more advanced functionality. Finally, we'll see how to easily create an UI editor for DOM model elements. +Now let us explore more thoroughly what the DOM can do, and look at possible ways of representing various XML concepts such as tag content, attributes or sub-tags. +Later we will discuss basic methods for working with the model, as well as cover more advanced functionality. +Finally, we'll see how to easily create an UI editor for DOM model elements. ## Building the Model ### Tag Content -In XML PSI, tag content is referred to as tag value, so well do the same for consistency. To read and change a tag value, you have to add two methods (getter and setter) to your interface, like this: +In XML PSI, tag content is referred to as tag value, so well do the same for consistency. +To read and change a tag value, you have to add two methods (getter and setter) to your interface, like this: ```java String getValue(); void setValue(String s); ``` -These method names (`getValue` and `setValue`) are standard, and they are used for accessing tag values by default. If you want to use custom method names for the same goal, you should annotate these methods with `@TagValue`, for example: +These method names (`getValue` and `setValue`) are standard, and they are used for accessing tag values by default. +If you want to use custom method names for the same goal, you should annotate these methods with `@TagValue`, for example: ```java @TagValue @@ -118,13 +137,25 @@ String getTagValue(); void setTagValue(String s); ``` -As you can see, our accessors work with `String` values. This is natural, since XML represents a text format, and tag content is always text. But sometimes you may want to operate with integers, booleans, enums, or even class names (they, of course, will be represented as `PsiClass`), and more generic Java types (`PsiType`). In such cases, you just need to change the type in methods to the one you need, and everything will keep working correctly. +As you can see, our accessors work with `String` values. +This is natural, since XML represents a text format, and tag content is always text. +But sometimes you may want to operate with integers, booleans, enums, or even class names (they, of course, will be represented as `PsiClass`), and more generic Java types (`PsiType`). +In such cases, you just need to change the type in methods to the one you need, and everything will keep working correctly. #### Custom Value Types -If you operate with even more exotic types, you should tell DOM how to deal with them. First, annotate your accessor methods with the `@Convert` annotation, and specify your own class that should extend the `Converter` class in the annotation. Here `T` is your exotic type, while `Converter` is a thing that knows how to convert values between `String` and `T`. If the value cannot be converted (for example, "foo" is not convertible into `Integer`), the converter may return `null`. Please also note that your implementation should have a no-argument constructor. +If you operate with even more exotic types, you should tell DOM how to deal with them. +First, annotate your accessor methods with the `@Convert` annotation, and specify your own class that should extend the `Converter` class in the annotation. +Here `T` is your exotic type, while `Converter` is a thing that knows how to convert values between `String` and `T`. +If the value cannot be converted (for example, "foo" is not convertible into `Integer`), the converter may return `null`. +Please also note that your implementation should have a no-argument constructor. -Let us consider an interesting case when `T` represents an enum value. Usually, the converter just searches for enum elements with the names specified in XML. But sometimes, for their names, you may need or want to use values that are not valid Java identifiers. For example, CMP version in EJB may be "1.x" or "2.x", but you can't create Java enums with such names. For such cases, let your enum implement `NamedEnum` interface, and then name your enum elements as you wish. Now, just provide the `getValue()` implementation that will return the right value to match with XML contents, and voilà\! +Let us consider an interesting case when `T` represents an enum value. +Usually, the converter just searches for enum elements with the names specified in XML. +But sometimes, for their names, you may need or want to use values that are not valid Java identifiers. +For example, CMP version in EJB may be "1.x" or "2.x", but you can't create Java enums with such names. +For such cases, let your enum implement `NamedEnum` interface, and then name your enum elements as you wish. +Now, just provide the `getValue()` implementation that will return the right value to match with XML contents, and voilà\! In our example, the code will look as follows: ```java @@ -133,16 +164,18 @@ enum CmpVersion implements NamedEnum { CmpVersion_2_X ("2.x"); private final String value; - - private CmpVersion(String value) { - this.value = value; + + private CmpVersion(String value) { + this.value = value; } public String getValue() { return value; } } ``` -As we have already mentioned, an XML tag may have lots of artifacts besides its value: there can be attributes, children, but rather often (e.g., according to DTD or Schema) it should have only the value. Of course such tags also need a DOM element to associate with. And we provide such an element: +As we have already mentioned, an XML tag may have lots of artifacts besides its value: there can be attributes, children, but rather often (e.g., according to DTD or Schema) it should have only the value. +Of course such tags also need a DOM element to associate with. +And we provide such an element: ```java interface GenericDomValue { @@ -157,11 +190,18 @@ interface GenericDomValue { } ``` -So, you can just specify a particular `T` when using this interface --- and everything will work. Methods that work with `String` are provided for many reasons. For example, your `T` is [`PsiClass`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiClass.java). It would be useful to highlight invalid values in UI. To get the value to highlight (the string from the XML file) we have the `getStringValue()` method. The error message will be taken from the converter via `getErrorMessage()`. +So, you can just specify a particular `T` when using this interface --- and everything will work. +Methods that work with `String` are provided for many reasons. +For example, your `T` is [`PsiClass`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiClass.java). +It would be useful to highlight invalid values in UI. +To get the value to highlight (the string from the XML file) we have the `getStringValue()` method. +The error message will be taken from the converter via `getErrorMessage()`. ### Attributes -Attributes are also rather simple to deal with. You can read their values, set them, and operate with different types. So it's natural to create something like `GenericDomValue` and then work as usual. "Something like" will be an inheritor, as shown below: +Attributes are also rather simple to deal with. +You can read their values, set them, and operate with different types. +So it's natural to create something like `GenericDomValue` and then work as usual. "Something like" will be an inheritor, as shown below: ```java interface GenericAttributeValue extends GenericDomValue { @@ -176,22 +216,35 @@ Consider that you want to work with an attribute named _some-class_ having a val GenericAttributeValue getMyAttributeValue(); ``` -That's all\! Now you can get/set values, resolve this `PsiClass`, get its `String` representation, etc. The name of the attribute will be taken from the method name (see next paragraph). If you name your method in a special way, you can even omit the annotation. For example: +That's all\! Now you can get/set values, resolve this `PsiClass`, get its `String` representation, etc. +The name of the attribute will be taken from the method name (see next paragraph). +If you name your method in a special way, you can even omit the annotation. +For example: ```java GenericAttributeValue getSomeClass(); ``` -The [`DomNameStrategy`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/DomNameStrategy.java) interface specifies how to convert accessor names to XML element names. Or more precisely, not the full accessor names, but rather the names minus any "get", "set" or "is" prefixes. The strategy class is specified in the `@NameStrategy` annotation in any DOM element interface. Then any descendants and children of this interface will use this strategy. The default strategy is [`HyphenNameStrategy`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/HyphenNameStrategy.java), where words are delimited by hyphens (see sample above). Another common variant is [`JavaNameStrategy`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/JavaNameStrategy.java) that capitalizes the first letter of each word, as in Java's naming convention. In our example, the attribute name would be "someClass". +The [`DomNameStrategy`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/DomNameStrategy.java) interface specifies how to convert accessor names to XML element names. +Or more precisely, not the full accessor names, but rather the names minus any "get", "set" or "is" prefixes. +The strategy class is specified in the `@NameStrategy` annotation in any DOM element interface. +Then any descendants and children of this interface will use this strategy. +The default strategy is [`HyphenNameStrategy`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/HyphenNameStrategy.java), where words are delimited by hyphens (see sample above). +Another common variant is [`JavaNameStrategy`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/JavaNameStrategy.java) that capitalizes the first letter of each word, as in Java's naming convention. +In our example, the attribute name would be "someClass". If attribute doesn't define a `PsiClass`, but some other custom `T` that needs a converter, you just need to specify the `@Convert` annotation to the getter. -Please note that the attributes getter method will never return `null`, even if the attribute isn't specified in XML. Its `getValue()`, `getStringValue()` and `getXmlAttribute()` methods will return `null`, but the DOM interface instance will exist and be valid. If the element has an underlying attribute, this can be easily fixed (surely, only if you need that): just call the `undefine()` method (defined in `DomElement`), and the XML attribute disappears, while [`GenericAttributeValue`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/GenericAttributeValue.java) remains valid. +Please note that the attributes getter method will never return `null`, even if the attribute isn't specified in XML. +Its `getValue()`, `getStringValue()` and `getXmlAttribute()` methods will return `null`, but the DOM interface instance will exist and be valid. +If the element has an underlying attribute, this can be easily fixed (surely, only if you need that): just call the `undefine()` method (defined in `DomElement`), and the XML attribute disappears, while [`GenericAttributeValue`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/GenericAttributeValue.java) remains valid. ### Children: Fixed Number -You may often deal with tags that have at most one sub-tag with the given name (e.g. ``, `` or ``) in tags defining entity EJBs. To work with such children, provide getters for them. These getters should have a return type that extends `DomElement`: +You may often deal with tags that have at most one sub-tag with the given name (e.g. ``, `` or ``) in tags defining entity EJBs. +To work with such children, provide getters for them. +These getters should have a return type that extends `DomElement`: ```java GenericDomValue getEjbName(); @@ -199,11 +252,22 @@ GenericDomValue getEjbClass(); CmpField getCmpField(); ``` -There's also an annotation to designate such children explicitly: `@SubTag`. Its "value" attribute contains a tag name. If it is not specified, the name is implied from the method name using the current name strategy. +There's also an annotation to designate such children explicitly: `@SubTag`. +Its "value" attribute contains a tag name. +If it is not specified, the name is implied from the method name using the current name strategy. -Sometimes it is the sub-tag's presence that means something, rather than its content --- `` in EJB method permissions, for example. If it exists, then permissions are unchecked, otherwise checked. For such things one should create a special `GenericDomValue` child. Usually its `getValue()` returns `true` if there's "true" in a tag value, `false` if there's "false" in a tag value, and `null` otherwise. In the `@SubTag` annotation, you can specify the attribute like `indicator=true`. In this case, `getValue()` will return `true` if the tag exists and `false` otherwise. +Sometimes it is the sub-tag's presence that means something, rather than its content --- `` in EJB method permissions, for example. +If it exists, then permissions are unchecked, otherwise checked. +For such things one should create a special `GenericDomValue` child. +Usually its `getValue()` returns `true` if there's "true" in a tag value, `false` if there's "false" in a tag value, and `null` otherwise. +In the `@SubTag` annotation, you can specify the attribute like `indicator=true`. +In this case, `getValue()` will return `true` if the tag exists and `false` otherwise. -Let's consider another interesting example inspired by EJB, where there is a relation that has two roles, each designating one relation end: first role and second role. Both are represented by tags with the same values. So, we could create a collection of role elements, and every time we access some role we would check if this collection has sufficient number of elements. But one of the main purposes of the DOM is to eliminate unnecessary checks. So why cant we have a fixed (more than one) number of children with the same tag name? Let's have them\! +Let's consider another interesting example inspired by EJB, where there is a relation that has two roles, each designating one relation end: first role and second role. +Both are represented by tags with the same values. +So, we could create a collection of role elements, and every time we access some role we would check if this collection has sufficient number of elements. +But one of the main purposes of the DOM is to eliminate unnecessary checks. +So why cant we have a fixed (more than one) number of children with the same tag name? Let's have them\! ```java @SubTag(value = "ejb-relationship-role", index = 0) @@ -213,13 +277,20 @@ EjbRelationshipRole getEjbRelationshipRole1(); EjbRelationshipRole getEjbRelationshipRole2(); ``` -The first method will return the DOM element for the first subtag named ``, and the second --- for the second one. Hence the term "fixed-number" for such children. According to DTD or Schema, there should be fixed number of subtags with the given name. Most often this fixed number is 1; in our case with the relations it is 2. Just like attributes, fixed-number children exist regardless of underlying tag existence. If you need to delete tags, it can be done with the help of the same `undefine()` method. +The first method will return the DOM element for the first subtag named ``, and the second --- for the second one. +Hence the term "fixed-number" for such children. +According to DTD or Schema, there should be fixed number of subtags with the given name. +Most often this fixed number is 1; in our case with the relations it is 2. +Just like attributes, fixed-number children exist regardless of underlying tag existence. +If you need to delete tags, it can be done with the help of the same `undefine()` method. For children of [`GenericDomValue`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/GenericDomValue.java) type, you can also specify a converter, just as you can for attributes. ### Children: Collections -One more common case in DTD and Schemas is when children have the same tag name and a non-fixed upper limit in count. Their accessors differ from those of the fixed-number children in the following: the return result is `Collection` or `List` of a special type that extends `DomElement`, and if you want to use name strategies, the method name must be in pluralized form. For example, in EJB we would have the following method: +One more common case in DTD and Schemas is when children have the same tag name and a non-fixed upper limit in count. +Their accessors differ from those of the fixed-number children in the following: the return result is `Collection` or `List` of a special type that extends `DomElement`, and if you want to use name strategies, the method name must be in pluralized form. +For example, in EJB we would have the following method: ```java List getEntities(); @@ -227,9 +298,16 @@ List getEntities(); There's also an annotation `@SubTagList` where you can explicitly specify the tag name. -Returned collections cannot be modified directly. To delete an element from collection, just call `undefine()` on this element. The tag will then be removed, and element will become invalid (`DomElement.isValid() == false`). Note that this behavior differs from that of fixed-number children and attributes: they are always valid, even after `undefine()`. Again, unlike those children types, collection children always have valid underlying XML tags. +Returned collections cannot be modified directly. +To delete an element from collection, just call `undefine()` on this element. +The tag will then be removed, and element will become invalid (`DomElement.isValid() == false`). +Note that this behavior differs from that of fixed-number children and attributes: they are always valid, even after `undefine()`. +Again, unlike those children types, collection children always have valid underlying XML tags. -Adding elements is a little bit harder. Since all DOM elements are created internally, you can't just pass some of your DOM elements to some method, to add the element to the collection. In fact, you have to ask a parent element to add a child to the collection. In our example it's done in the following way: +Adding elements is a little bit harder. +Since all DOM elements are created internally, you can't just pass some of your DOM elements to some method, to add the element to the collection. +In fact, you have to ask a parent element to add a child to the collection. +In our example it's done in the following way: ```java Entity addEntity(int index); @@ -241,11 +319,14 @@ which adds an element to wherever you want, or Entity addEntity(); ``` -which adds a new DOM element to the end of the collection. Please note the singular tense of the word "Entity". That's because here we deal with one `Entity` object, while in the collection getter we dealt with potentially many entities. +which adds a new DOM element to the end of the collection. +Please note the singular tense of the word "Entity". +That's because here we deal with one `Entity` object, while in the collection getter we dealt with potentially many entities. Now, you can do anything you want with the returned value: modify, define the tag's value, children, etc. -The last common case is also a collection, but one consisting of tags with different names that are arbitrarily mixed. To work with it, you should define collection getters for all tag names within the mixed collection, and then define an additional specially annotated getter: +The last common case is also a collection, but one consisting of tags with different names that are arbitrarily mixed. +To work with it, you should define collection getters for all tag names within the mixed collection, and then define an additional specially annotated getter: ```java // elements @@ -271,12 +352,14 @@ To add elements to such mixed collections, you should create "add" methods for e The index parameter in the last example means the index in the merged collection, not in the collection of tags named "bar". ### Dynamic Definition -You can extend existing DOM model at runtime by implementing `com.intellij.util.xml.reflect.DomExtender`. Register it in "extenderClass" attribute of EP `com.intellij.dom.extender`, where "domClass" specifies DOM class `` to be extended. [`DomExtensionsRegistrar`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/reflect/DomExtensionsRegistrar.java) provides various methods to register dynamic attributes and children. +You can extend existing DOM model at runtime by implementing `com.intellij.util.xml.reflect.DomExtender`. +Register it in "extenderClass" attribute of EP `com.intellij.dom.extender`, where "domClass" specifies DOM class `` to be extended. [`DomExtensionsRegistrar`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/reflect/DomExtensionsRegistrar.java) provides various methods to register dynamic attributes and children. If the contributed elements depend on anything other than plain XML file content (used framework version, libraries in classpath, ...), make sure to return `false` from `DomExtender.supportsStubs()`. ### Generating DOM from Existing XSD -DOM can be generated automatically from existing XSD/DTD. Output correctness/completeness will largely depend on the input scheme and may require additional manual adjustments. +DOM can be generated automatically from existing XSD/DTD. +Output correctness/completeness will largely depend on the input scheme and may require additional manual adjustments. Follow these steps: @@ -294,9 +377,14 @@ _Plugin DevKit_ supports the following features for working with DOM related cod ## Working with the DOM ### Class Choosers -It often happens that a collection contains same-named tags that may have different structure or even be represented by different types in the DTD or Schema. As an example, JSF Managed Beans may be of three types. If a `` tag contains a `` sub-tag, then the Managed Bean type is `MapEntriesBean`. If it contains a `` sub-tag — can you guess? Right — `ListEntriesBean`! Otherwise it's a `PropertyBean` (all three interfaces extend `ManagedBean`). And when we write `List getManagedBeans()`, we expect to get not only a list where all elements are instances of the `ManagedBean` interface, but a list where each element is of a certain type, i.e. `MapEntriesBean`, `ListEntriesBean`, or `PropertyBean`. +It often happens that a collection contains same-named tags that may have different structure or even be represented by different types in the DTD or Schema. +As an example, JSF Managed Beans may be of three types. +If a `` tag contains a `` sub-tag, then the Managed Bean type is `MapEntriesBean`. +If it contains a `` sub-tag — can you guess? Right — `ListEntriesBean`! Otherwise it's a `PropertyBean` (all three interfaces extend `ManagedBean`). +And when we write `List getManagedBeans()`, we expect to get not only a list where all elements are instances of the `ManagedBean` interface, but a list where each element is of a certain type, i.e. `MapEntriesBean`, `ListEntriesBean`, or `PropertyBean`. -In such cases one should decide which interface the DOM element should actually implement (according to the given tag). This is achieved by extending the [`TypeChooser`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/TypeChooser.java) abstract class: +In such cases one should decide which interface the DOM element should actually implement (according to the given tag). +This is achieved by extending the [`TypeChooser`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/TypeChooser.java) abstract class: ```java public abstract class TypeChooser { @@ -306,7 +394,9 @@ public abstract class TypeChooser { } ``` -Here, the first method (`chooseType()`) does exactly what it is named after (chooses the particular type, most often it's a class). The second one (`distinguishTag()`) acts in reverse: it modifies a tag so that when the element is read from an XML file next time (for example, after the user has closed and opened the project again), the newly created DOM element will implement the same interface and no model data will be lost. Finally, `getChooserTypes()` just returns all the types that could be returned by `chooseType()`. +Here, the first method (`chooseType()`) does exactly what it is named after (chooses the particular type, most often it's a class). +The second one (`distinguishTag()`) acts in reverse: it modifies a tag so that when the element is read from an XML file next time (for example, after the user has closed and opened the project again), the newly created DOM element will implement the same interface and no model data will be lost. +Finally, `getChooserTypes()` just returns all the types that could be returned by `chooseType()`. To make your `TypeChooser` work, register it in your overridden `DomFileDescription.initializeFileDescription()` method by calling `registerTypeChooser()`. @@ -314,38 +404,61 @@ To make your `TypeChooser` work, register it in your overridden `DomFileDescript #### PSI Connection -Of course, DOM is tightly connected to XML PSI, so there's always a way of getting the `XmlTag` instance (which can be `null` for fixed-number children and attributes) using the `getXmlTag()` method. We remember that in `GenericAttributeValue` there's also the `getXmlAttribute()` method. In general case there is `getXmlElement()` method. You can also get a DOM element by its underlying XML PSI element using the `DomManager.getDomElement()` method. +Of course, DOM is tightly connected to XML PSI, so there's always a way of getting the `XmlTag` instance (which can be `null` for fixed-number children and attributes) using the `getXmlTag()` method. +We remember that in `GenericAttributeValue` there's also the `getXmlAttribute()` method. +In general case there is `getXmlElement()` method. +You can also get a DOM element by its underlying XML PSI element using the `DomManager.getDomElement()` method. -If DOM element has no underlying XML element, it can be created by calling `ensureTagExists()`. To delete a tag, use the already known `undefine()` method. This method will always delete the underlying XML element (tag or attribute). If the element was a collection child, then neither it nor its entire sub-tree will be valid anymore. +If DOM element has no underlying XML element, it can be created by calling `ensureTagExists()`. +To delete a tag, use the already known `undefine()` method. +This method will always delete the underlying XML element (tag or attribute). +If the element was a collection child, then neither it nor its entire sub-tree will be valid anymore. #### Tree Structure -In every normal tree there's always a possibility to walk up. `DomElement` is no exception. Method `getParent()` just returns element's parent in tree. +In every normal tree there's always a possibility to walk up. `DomElement` is no exception. +Method `getParent()` just returns element's parent in tree. -The method ` T getParentOfType(Class requiredClass, boolean strict)` returns the tree ancestor of the given class. You can see the standard _strict_ parameter, that can return the DOM element itself, if it's `false` and your current DOM element is an instance of _requiredClass_. +The method ` T getParentOfType(Class requiredClass, boolean strict)` returns the tree ancestor of the given class. +You can see the standard _strict_ parameter, that can return the DOM element itself, if it's `false` and your current DOM element is an instance of _requiredClass_. Finally, `getRoot()` will return the `DomFileElement`, which is the root of every DOM tree. #### Validity -An element becomes invalid if it has been deleted explicitly or due to external PSI changes. Fixed-number children and attributes are meant to stay valid as long as possible, no matter what happens with XML. They can become invalid only if they have collection tree ancestor that has been deleted. +An element becomes invalid if it has been deleted explicitly or due to external PSI changes. +Fixed-number children and attributes are meant to stay valid as long as possible, no matter what happens with XML. +They can become invalid only if they have collection tree ancestor that has been deleted. Newly created DOM elements are always correct and valid, so their `isValid()` methods will return `true`. Element validity is very important, since you cannot invoke any methods on invalid elements (except, of course, `isValid()` itself). #### DOM Reflection -DOM also has a kind of reflection, called "Generic Info". One would use it to be able to access children by tag names directly, instead of calling getter methods. See [`DomGenericInfo`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/reflect/DomGenericInfo.java) interface and `getGenericInfo()` methods in `DomElement` and `DomManager` for more information. There's also `DomElement.getXmlElementName()` method that returns the name of a corresponding tag or attribute. +DOM also has a kind of reflection, called "Generic Info". +One would use it to be able to access children by tag names directly, instead of calling getter methods. +See [`DomGenericInfo`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/reflect/DomGenericInfo.java) interface and `getGenericInfo()` methods in `DomElement` and `DomManager` for more information. +There's also `DomElement.getXmlElementName()` method that returns the name of a corresponding tag or attribute. #### Presentation -`DomElement.getPresentation()` returns an instance of [`ElementPresentation`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ElementPresentation.java), an interface that knows presentable element type, name, and sometimes even its icon. Presentations are actually obtained from presentation factory objects that, like ClassChoosers's, should be registered in [`ElementPresentationManager`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ElementPresentationManager.java) as early as possible. You can specify type name and icon for all elements of some class, ways of getting type name, icon and presentable name for particular objects. When not specified, presentable name is taken from the object itself, if it contains a method annotated with `@NameValue` annotation, that returns `String` or `GenericValue`. If there's no such method, it will return `null`. For `DomElement`, there's another way to get this presentable name: +`DomElement.getPresentation()` returns an instance of [`ElementPresentation`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ElementPresentation.java), an interface that knows presentable element type, name, and sometimes even its icon. +Presentations are actually obtained from presentation factory objects that, like ClassChoosers's, should be registered in [`ElementPresentationManager`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ElementPresentationManager.java) as early as possible. +You can specify type name and icon for all elements of some class, ways of getting type name, icon and presentable name for particular objects. +When not specified, presentable name is taken from the object itself, if it contains a method annotated with `@NameValue` annotation, that returns `String` or `GenericValue`. +If there's no such method, it will return `null`. +For `DomElement`, there's another way to get this presentable name: `DomElement.getGenericInfo().getElementName()`. #### Events -If you want to be notified on every change in the DOM model, add `DomEventListener` to `DomManager`. DOM supports the following events: tag value changed, element defined/undefined/changed, and collection child added/removed. +If you want to be notified on every change in the DOM model, add `DomEventListener` to `DomManager`. +DOM supports the following events: tag value changed, element defined/undefined/changed, and collection child added/removed. #### Highlighting Annotations -The DOM supports error checking and highlighting. It's based on annotations which you add to the DOM element in a special place (don't confuse these annotations with the ones of Java 5 — they are very different). You need to implement the [`DomElementAnnotator`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/highlighting/DomElementsAnnotator.java) interface, and override `DomFileDescription.createAnnotator()` method, and create this annotator there. In `DomElementsAnnotator.annotate(DomElement element, DomElementsProblemsHolder annotator)` you should report about all errors and warnings in the element's sub-tree to the annotator (`DomElementsProblemsHolder.createProblem()`). You should return this annotator in the corresponding virtual method of the `DomFileDescription`. +The DOM supports error checking and highlighting. +It's based on annotations which you add to the DOM element in a special place (don't confuse these annotations with the ones of Java 5 — they are very different). +You need to implement the [`DomElementAnnotator`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/highlighting/DomElementsAnnotator.java) interface, and override `DomFileDescription.createAnnotator()` method, and create this annotator there. +In `DomElementsAnnotator.annotate(DomElement element, DomElementsProblemsHolder annotator)` you should report about all errors and warnings in the element's sub-tree to the annotator (`DomElementsProblemsHolder.createProblem()`). +You should return this annotator in the corresponding virtual method of the `DomFileDescription`. #### Automatic Highlighting (BasicDomElementsInspection) The following errors can be highlighted automatically by providing an instance of `BasicDomElementsInspection`: @@ -354,33 +467,66 @@ The following errors can be highlighted automatically by providing an instance o - XML value cannot be converted by some `Converter` - name is not unique while it should be -The latter case requires you to specify the name getter with `@NameValue` annotation. The checking uses the `DomFileDescription.getIdentityScope()` method to get the element defining the root scope in which the name should be unique. +The latter case requires you to specify the name getter with `@NameValue` annotation. +The checking uses the `DomFileDescription.getIdentityScope()` method to get the element defining the root scope in which the name should be unique. To suppress spellchecking annotate your DomElement with `@com.intellij.spellchecker.xml.NoSpellchecking`. #### Required Children -There is a common case in error highlighting, when one needs to say, that some required sub-tag or attribute is missing. DOM will do this for you automatically, if you annotate the getter for that child with the `@Required` annotation. For collection children getters, this annotation will mean, that the collection should be not empty (corresponding to '+' sign in DTD). Also, when you create a new element that has required fixed-number or attribute children, their tags or attributes will also be created in XML. +There is a common case in error highlighting, when one needs to say, that some required sub-tag or attribute is missing. +DOM will do this for you automatically, if you annotate the getter for that child with the `@Required` annotation. +For collection children getters, this annotation will mean, that the collection should be not empty (corresponding to '+' sign in DTD). +Also, when you create a new element that has required fixed-number or attribute children, their tags or attributes will also be created in XML. ### Resolving -Remember the interface `GenericDomValue` and its sub-interface `GenericAttributeValue`? Remember, that ANY class may be passed as `T` — for example, let's interpret `GenericDomValue` as a reference to a class. Then we can always consider it as a reference to an object of class `T`! With Strings or enums, it is not a very useful idea, but we'll use it in another way. Very often XML has such a structure that an object is declared at some place, and is referenced at some other place (more precisely, in a tag or attribute value). So, if you want to create a method like `GenericValue getMyDomElementReference()`, then you just have to specify a proper converter that will find an instance in your model of `MyDomElement` with the name specified in the `GenericDomValue`. +Remember the interface `GenericDomValue` and its sub-interface `GenericAttributeValue`? Remember, that ANY class may be passed as `T` — for example, let's interpret `GenericDomValue` as a reference to a class. +Then we can always consider it as a reference to an object of class `T`! With Strings or enums, it is not a very useful idea, but we'll use it in another way. +Very often XML has such a structure that an object is declared at some place, and is referenced at some other place (more precisely, in a tag or attribute value). +So, if you want to create a method like `GenericValue getMyDomElementReference()`, then you just have to specify a proper converter that will find an instance in your model of `MyDomElement` with the name specified in the `GenericDomValue`. -That's the core idea. Since creating such converters is quite boring, we've done it for you. You don't have to annotate reference getters at all, as the name resolution will be made automatically. Elements will be searched by name, and the name will be taken from the method annotated with `@NameValue`. The converter used is [`DomResolveConverter`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/DomResolveConverter.java). Its constructor takes a parameter, so it can't be referenced in `@Convert` annotation, but its subclasses (if you create them) — can. If you still want to specify explicitly that your reference to `DomElement` should be resolved "model-wide", use the `@Resolve` annotation parameterized with the desired class. The resolution scope will be taken from the `DomFileDescription.getResolveScope()`. +That's the core idea. +Since creating such converters is quite boring, we've done it for you. +You don't have to annotate reference getters at all, as the name resolution will be made automatically. +Elements will be searched by name, and the name will be taken from the method annotated with `@NameValue`. +The converter used is [`DomResolveConverter`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/DomResolveConverter.java). +Its constructor takes a parameter, so it can't be referenced in `@Convert` annotation, but its subclasses (if you create them) — can. +If you still want to specify explicitly that your reference to `DomElement` should be resolved "model-wide", use the `@Resolve` annotation parameterized with the desired class. +The resolution scope will be taken from the `DomFileDescription.getResolveScope()`. -In addition to the above, auto-resolving in DOM also provides some features in your XML text editor: error highlighting, completion, Find Usages, Rename Refactoring... Unresolved references will be highlighted, and even completed. If you want to create a custom converter and want to have this code insight with it, you should extend not only the [`Converter`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/Converter.java) but [`ResolvingConverter`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ResolvingConverter.java). It has one more method `getVariants()`, where you'll have to provide the collection consisting of all targets your reference may resolve to. Those familiar with [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) will recognize the similarities here. +In addition to the above, auto-resolving in DOM also provides some features in your XML text editor: error highlighting, completion, Find Usages, Rename Refactoring... +Unresolved references will be highlighted, and even completed. +If you want to create a custom converter and want to have this code insight with it, you should extend not only the [`Converter`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/Converter.java) but [`ResolvingConverter`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ResolvingConverter.java). +It has one more method `getVariants()`, where you'll have to provide the collection consisting of all targets your reference may resolve to. +Those familiar with [`PsiReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiReference.java) will recognize the similarities here. If you need to choose a `Converter` depending on other values (e.g. in sibling/parent element) or any runtime condition (e.g. presence or version of library), you can use `WrappingConverter`. See also `GenericDomValueConvertersRegistry` for managing an extensible registry of available Converters to choose from. ### Mock and Stable Elements -Your DOM elements do not have to be tied to a physical file. `DomManager.createMockElement()` will help you to create a virtual element of a given class with the given module. An element may be physical or not. 'Physical' here means that DOM will create a mock document for it, so you can enjoy Undo functionality if you pass this document to the right place in file editor. +Your DOM elements do not have to be tied to a physical file. `DomManager.createMockElement()` will help you to create a virtual element of a given class with the given module. +An element may be physical or not. 'Physical' here means that DOM will create a mock document for it, so you can enjoy Undo functionality if you pass this document to the right place in file editor. -`DomElement.copyFrom()` allows you to copy information from one `DomElement` to another. In fact, it just replaces XML tags, and all the old data is lost. Nevertheless, the element's fixed-number children don't become invalid, they only contain new tag values, attribute values, etc. The tree is actually rather conservative. +`DomElement.copyFrom()` allows you to copy information from one `DomElement` to another. +In fact, it just replaces XML tags, and all the old data is lost. +Nevertheless, the element's fixed-number children don't become invalid, they only contain new tag values, attribute values, etc. +The tree is actually rather conservative. -The combination of `createMockElement()` and `copyFrom()` is useful for editing element contents in dialogs. You create a mock copy of an element, work with it in the dialog and then, if the user doesn't cancel, copy the element back to the main model. Since it's a common case, a special shortcut method has been created in `DomElement`, called `createMockCopy()`. +The combination of `createMockElement()` and `copyFrom()` is useful for editing element contents in dialogs. +You create a mock copy of an element, work with it in the dialog and then, if the user doesn't cancel, copy the element back to the main model. +Since it's a common case, a special shortcut method has been created in `DomElement`, called `createMockCopy()`. -IntelliJ Platform's XML parser is incremental: changes in text do not cause the whole file to be reparsed. But you should keep in mind that this rule may sometimes not work correctly. For example, your DOM elements can unexpectedly become broken as a result of manual editing of the XML file (even if it didn't happen inside those elements). If a file editor depends on such a broken element, this can lead to closing the tab, which isn't very nice from the user's point of view. For example, suppose you have an entity bean named "SomeEntity". You open an editor for it, then you go into the XML, change the tag name from entity to session, and then back to entity. Of course, no DOM element can survive after such blasphemy. But notwithstanding, you still want your editor to stay open! Well, there is a solution, and it's called `DomManager.createStableValue(Factory factory)`. -This method creates a DOM element that delegates all its functionality to some real element (returned from the factory parameter). As soon as that real element becomes invalid, the factory is called once more, and if it returns something valid, it becomes the new delegate. And so on... In the example with EJB, the factory would once again look for an Entity Bean named "SomeEntity". +IntelliJ Platform's XML parser is incremental: changes in text do not cause the whole file to be reparsed. +But you should keep in mind that this rule may sometimes not work correctly. +For example, your DOM elements can unexpectedly become broken as a result of manual editing of the XML file (even if it didn't happen inside those elements). +If a file editor depends on such a broken element, this can lead to closing the tab, which isn't very nice from the user's point of view. +For example, suppose you have an entity bean named "SomeEntity". +You open an editor for it, then you go into the XML, change the tag name from entity to session, and then back to entity. +Of course, no DOM element can survive after such blasphemy. +But notwithstanding, you still want your editor to stay open! Well, there is a solution, and it's called `DomManager.createStableValue(Factory factory)`. +This method creates a DOM element that delegates all its functionality to some real element (returned from the factory parameter). +As soon as that real element becomes invalid, the factory is called once more, and if it returns something valid, it becomes the new delegate. +And so on... In the example with EJB, the factory would once again look for an Entity Bean named "SomeEntity". Stable DOM elements also implement the `StableElement` interface, which has the following methods: @@ -389,7 +535,13 @@ Stable DOM elements also implement the `StableElement` interface, which has the * `void revalidate()` — calls the factory, and if it returns something new (i.e. not the same as the current wrapped element) invalidates the old value and adopts the new one. ### Visitor -Visitor is a very common design pattern. DOM model also has a visitor, and it's called `DomElementVisitor`. The `DomElement` interface has methods `accept()` and `acceptChildren()` that take this visitor as a parameter. If you look at the interface `DomElementVisitor` itself, you may be surprised, since it has only one method: `visitDomElement(DomElement)`. Where is the Visitor pattern? Where are all those methods with names like `visitT(T)` that are usually found in it? There are no such methods, because the actual interfaces (T's) aren't known to anyone except you. But when you instantiate the `DomElementVisitor` interface, you may add there these `visitT()` methods, and they will be called! You may even name them just `visit()`, specify the type of the parameter, and everything will be fine. For example, if you have two DOM element classes — `Foo` and `Bar` — your visitor may look like this: +Visitor is a very common design pattern. +DOM model also has a visitor, and it's called `DomElementVisitor`. +The `DomElement` interface has methods `accept()` and `acceptChildren()` that take this visitor as a parameter. +If you look at the interface `DomElementVisitor` itself, you may be surprised, since it has only one method: `visitDomElement(DomElement)`. +Where is the Visitor pattern? Where are all those methods with names like `visitT(T)` that are usually found in it? There are no such methods, because the actual interfaces (T's) aren't known to anyone except you. +But when you instantiate the `DomElementVisitor` interface, you may add there these `visitT()` methods, and they will be called! You may even name them just `visit()`, specify the type of the parameter, and everything will be fine. +For example, if you have two DOM element classes — `Foo` and `Bar` — your visitor may look like this: ```java class MyVisitor implements DomElementVisitor { @@ -400,9 +552,13 @@ class MyVisitor implements DomElementVisitor { ``` ### Implementation -Sometimes you may want to extend your model with some functionality that isn't directly connected with XML, but relates to your program logic. And the most appropriate place for this functionality is the DOM element interface. What to do then? +Sometimes you may want to extend your model with some functionality that isn't directly connected with XML, but relates to your program logic. +And the most appropriate place for this functionality is the DOM element interface. +What to do then? -The simplest case is when you want to add to your interface a method that returns exactly what some other getter in this element (or in one of its children) returns. You can easily write this helper method and annotate it with the `@PropertyAccessor` annotation, in which you should specify the path consisting of property names (getter names without the "get" or "is" prefixes). For example, you can write: +The simplest case is when you want to add to your interface a method that returns exactly what some other getter in this element (or in one of its children) returns. +You can easily write this helper method and annotate it with the `@PropertyAccessor` annotation, in which you should specify the path consisting of property names (getter names without the "get" or "is" prefixes). +For example, you can write: ```java GenericDomValue getVeryLongName() @@ -411,101 +567,184 @@ GenericDomValue getVeryLongName() GenericDomValue getName() ``` -In this case, the second method will return just the same as the first one. If there were "foo.bar.name" instead of "very-long-name" in the annotation, the system would actually call `getFoo().getBar().getName()` and return the result to you. Such annotations are useful when you're extending some interface that is inconsistent with your model, or you try to extract a common super-interface from two model interfaces with differently named children that have the same sense (see `` and ``). +In this case, the second method will return just the same as the first one. +If there were "foo.bar.name" instead of "very-long-name" in the annotation, the system would actually call `getFoo().getBar().getName()` and return the result to you. +Such annotations are useful when you're extending some interface that is inconsistent with your model, or you try to extract a common super-interface from two model interfaces with differently named children that have the same sense (see `` and ``). -The case just described is simple, but rare. More often, you really have to incorporate some logic into your model. Then nothing except Java code helps you. And it will. Add the desired methods to your interface, then create an abstract class implementing the interface, and implement there only methods that you added manually and that are not directly connected to your XML model. Note that the class should have a constructor with no arguments. +The case just described is simple, but rare. +More often, you really have to incorporate some logic into your model. +Then nothing except Java code helps you. +And it will. +Add the desired methods to your interface, then create an abstract class implementing the interface, and implement there only methods that you added manually and that are not directly connected to your XML model. +Note that the class should have a constructor with no arguments. -Now you only have to let DOM know that you wish to use this implementation every time you're creating a model element that should implement the necessary interface. Simply register it using -extension point `com.intellij.dom.implementation` and DOM will generate at run-time the class that not only implements the needed interface, but also extends your abstract class. +Now you only have to let DOM know that you wish to use this implementation every time you're creating a model element that should implement the necessary interface. +Simply register it using extension point `com.intellij.dom.implementation` and DOM will generate at run-time the class that not only implements the needed interface, but also extends your abstract class. ### Models Across Multiple Files Many frameworks require a set of XML configuration files ("fileset") to work as one model, so resolving/navigation works across all related DOM files. Depending on implementation/plugin, providing filesets implicitly (using existing framework's setup in project) or via user configuration (usually via dedicated `Facet`) can be achieved. -Extend [`DomModelFactory`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/model/impl/DomModelFactory.java) (or [`BaseDomModelFactory`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/model/impl/BaseDomModelFactory.java) for non-`Module` scope) and provide implementation of your `DomModel`. Usually you will want to add searcher/utility methods to work with your `DomModel` implementation. +Extend [`DomModelFactory`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/model/impl/DomModelFactory.java) (or [`BaseDomModelFactory`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/model/impl/BaseDomModelFactory.java) for non-`Module` scope) and provide implementation of your `DomModel`. +Usually you will want to add searcher/utility methods to work with your `DomModel` implementation. Example can be found in Struts 2 plugin (package `com.intellij.struts2.dom.struts.model`). ### DOM Stubs > **NOTE** Please use it sparingly and only for heavily accessed parts in your DOM model, as it increases disk space usage/indexing run time. -DOM elements can be stubbed, so (costly) access to XML/PSI is not necessary (see [Indexing and PSI Stubs](/basics/indexing_and_psi_stubs.md) for similar feature for custom languages). Performance relevant elements, tag or attribute getters can simply be annotated with `@com.intellij.util.xml.Stubbed`. +DOM elements can be stubbed, so (costly) access to XML/PSI is not necessary (see [Indexing and PSI Stubs](/basics/indexing_and_psi_stubs.md) for similar feature for custom languages). +Performance relevant elements, tag or attribute getters can simply be annotated with `@com.intellij.util.xml.Stubbed`. Return `true` from `DomFileDescription.hasStubs()` and increase `DomFileDescription.getStubVersion()` whenever you change `@Stubbed` annotations usage in your DOM hierarchy to trigger proper rebuilding of Stubs during indexing. ## Building a DOM-Based GUI ### Forms -All forms that deal with DOM are organized in a special way. They support two main things: getting data from XML into the UI, and saving UI data to XML. The former is called resetting, the latter — committing. There's [`Committable`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/Committable.java) interface that has corresponding methods: `commit()` and `reset()`. There's also a way of structuring your forms into smaller parts, namely the Composite pattern: [`CompositeCommittable`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/CompositeCommittable.java). Methods `commit()` and `reset()` are invoked automatically on editor tab switch or undo. So you only need to ensure that all your Swing structure is organized in a tree of `CompositeCommittable`, and all the hard work will be done by the IDE. +All forms that deal with DOM are organized in a special way. +They support two main things: getting data from XML into the UI, and saving UI data to XML. +The former is called resetting, the latter — committing. +There's [`Committable`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/Committable.java) interface that has corresponding methods: `commit()` and `reset()`. +There's also a way of structuring your forms into smaller parts, namely the Composite pattern: [`CompositeCommittable`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/CompositeCommittable.java). +Methods `commit()` and `reset()` are invoked automatically on editor tab switch or undo. +So you only need to ensure that all your Swing structure is organized in a tree of `CompositeCommittable`, and all the hard work will be done by the IDE. -DOM controls are special descendants of `Committable`. All of them implement `DomUIControl`. Note that they are not Swing components — they are only a way of connecting DOM model and Swing components. One end of the connection — the DOM element — is usually specified in the controls constructor. The other end — Swing component — can be obtained in 2 ways. The first is to ask DOM control to create it. But that is rather inconvenient if you want to create the forms in, say, IntelliJ IDEA's GUI Designer. In that case, you'll need the second way: ask the control to `bind()` to an existing Swing component of a correct type (that depends on the type of value that you're editing). After that, your Swing components will be synchronized with DOM, they'll even highlight errors reported by `DomElementsAnnotator`. +DOM controls are special descendants of `Committable`. +All of them implement `DomUIControl`. +Note that they are not Swing components — they are only a way of connecting DOM model and Swing components. +One end of the connection — the DOM element — is usually specified in the controls constructor. +The other end — Swing component — can be obtained in 2 ways. +The first is to ask DOM control to create it. +But that is rather inconvenient if you want to create the forms in, say, IntelliJ IDEA's GUI Designer. +In that case, you'll need the second way: ask the control to `bind()` to an existing Swing component of a correct type (that depends on the type of value that you're editing). +After that, your Swing components will be synchronized with DOM, they'll even highlight errors reported by `DomElementsAnnotator`. -Sometimes you may need to do some work (enable or disable some components, change their values) after a particular DOM control is committed. Then you should define the `addCommitListener()` method of that DOM control and override the `CommitListener.afterCommit()` method. This method will be invoked inside the same write action as the main `commit()`, so any changes you do in this method to the XML will be merged with the `commit()` in the Undo queue. +Sometimes you may need to do some work (enable or disable some components, change their values) after a particular DOM control is committed. +Then you should define the `addCommitListener()` method of that DOM control and override the `CommitListener.afterCommit()` method. +This method will be invoked inside the same write action as the main `commit()`, so any changes you do in this method to the XML will be merged with the `commit()` in the Undo queue. ### Simple Controls -With simple controls, you can edit `GenericDomValue`: simple text, class names, enums and boolean values. These controls take a special object as a constructor parameter. This object should implement the `DomWrapper` interface that knows how to set/get values to/from DOM model. +With simple controls, you can edit `GenericDomValue`: simple text, class names, enums and boolean values. +These controls take a special object as a constructor parameter. +This object should implement the `DomWrapper` interface that knows how to set/get values to/from DOM model. -We have three major DomWrapper's: [`DomFixedWrapper`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/DomFixedWrapper.java) redirecting calls to [`GenericDomValue`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/GenericDomValue.java), [`DomStringWrapper`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/DomStringWrapper.java) redirecting calls to string accessors of [`GenericDomValue`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/GenericDomValue.java), and [`DomCollectionWrapper`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/DomCollectionWrapper.java) that gets/sets values of the first element of the given [`GenericDomValue`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/GenericDomValue.java) collection. Some controls (those having a text field as part of itself) take additional boolean constructor parameter — _commitOnEveryChange_, whose meaning is evident from the name. We don't recommend using it anywhere except small dialogs, because committing on every change slows down the system significantly. +We have three major DomWrapper's: [`DomFixedWrapper`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/DomFixedWrapper.java) redirecting calls to [`GenericDomValue`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/GenericDomValue.java), [`DomStringWrapper`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/DomStringWrapper.java) redirecting calls to string accessors of [`GenericDomValue`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/GenericDomValue.java), and [`DomCollectionWrapper`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/DomCollectionWrapper.java) that gets/sets values of the first element of the given [`GenericDomValue`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/GenericDomValue.java) collection. +Some controls (those having a text field as part of itself) take additional boolean constructor parameter — _commitOnEveryChange_, whose meaning is evident from the name. +We don't recommend using it anywhere except small dialogs, because committing on every change slows down the system significantly. -Most often these controls are created by `DomUIFactory.createControl(GenericDomValue)`. This method understands which control to create by using DOM reflection (`DomGenericInfo`, as you probably remember). But sometimes you may want to create the controls directly. So let's look at the simple controls more closely. +Most often these controls are created by `DomUIFactory.createControl(GenericDomValue)`. +This method understands which control to create by using DOM reflection (`DomGenericInfo`, as you probably remember). +But sometimes you may want to create the controls directly. +So let's look at the simple controls more closely. ##### BooleanControl -It allows you to edit boolean values. The control is bound to `JCheckBox`. +It allows you to edit boolean values. +The control is bound to `JCheckBox`. ![BooleanControl](img/xml_dom_api/booleancontrol.gif) ##### ComboControl -The control is bound to a non-editable `JComboBox`, so it can be used to choose something from a limited set. One case of such a limited set is enum. Or it can be a constructor where you can provide a `Factory>`, and return from this factory anything you want (for example, a list of database names to choose from). By default, the wrong values (written in XML, but not present in the list you've given to the control) are displayed in red. Since it's common practice to specify custom `CellRenderer` for combo boxes, the control has the `isValidValue(String)` method. If it returns `false` on the value you're rendering, you can highlight it in some way, to achieve the same result as the default renderer. Or you can just delegate to that renderer in your own way. +The control is bound to a non-editable `JComboBox`, so it can be used to choose something from a limited set. +One case of such a limited set is enum. +Or it can be a constructor where you can provide a `Factory>`, and return from this factory anything you want (for example, a list of database names to choose from). +By default, the wrong values (written in XML, but not present in the list you've given to the control) are displayed in red. +Since it's common practice to specify custom `CellRenderer` for combo boxes, the control has the `isValidValue(String)` method. +If it returns `false` on the value you're rendering, you can highlight it in some way, to achieve the same result as the default renderer. +Or you can just delegate to that renderer in your own way. ![ComboControl](img/xml_dom_api/combocontrol.gif) ##### BooleanEnumControl -Sometimes, when there are only 2 alternatives, it's convenient to use a check box instead of combo box. This control is designed specially for such cases. While being (and being bound to) a check box, the control edits not just "true" or "false", but any two String values, or two enum elements. In the last case, it has a boolean _invertedOrder_ parameter, to specify which element corresponds to the checked state. By default _invertedOrder_ is set to `false`, so the first element corresponds to the unchecked state, and the second — to the checked one. If you set the parameter to `true`, the states will swap. +Sometimes, when there are only 2 alternatives, it's convenient to use a check box instead of combo box. +This control is designed specially for such cases. +While being (and being bound to) a check box, the control edits not just "true" or "false", but any two String values, or two enum elements. +In the last case, it has a boolean _invertedOrder_ parameter, to specify which element corresponds to the checked state. +By default _invertedOrder_ is set to `false`, so the first element corresponds to the unchecked state, and the second — to the checked one. +If you set the parameter to `true`, the states will swap. ### Editor-Based Controls -Please note that editor-based controls are built on IntelliJ Platform's `Editor` instead of standard `JTextField`. Since there's currently no way to instantiate Editor directly through the Open API, controls are bound to special `JPanel` inheritors, and their `bind()` method adds the necessary content to those panels. +Please note that editor-based controls are built on IntelliJ Platform's `Editor` instead of standard `JTextField`. +Since there's currently no way to instantiate Editor directly through the Open API, controls are bound to special `JPanel` inheritors, and their `bind()` method adds the necessary content to those panels. ##### TextControl -This control allows you to edit simple string values. The control is bound to a `TextPanel` component. There's also an inheritor of that panel — `MultiLineTextPanel`. If you bind a `StringControl` to it, a big editor will appear on the screen. In case you don't have space for a big editor, bind it to a `BigTextPanel`. Then it will be filled with a text editor, and the browse button will be added to open a dialog with the big editor where you can type a longer string. +This control allows you to edit simple string values. +The control is bound to a `TextPanel` component. +There's also an inheritor of that panel — `MultiLineTextPanel`. +If you bind a `StringControl` to it, a big editor will appear on the screen. +In case you don't have space for a big editor, bind it to a `BigTextPanel`. +Then it will be filled with a text editor, and the browse button will be added to open a dialog with the big editor where you can type a longer string. ##### PsiClassControl -This is a one-line editor with a browse button that opens the standard class selection dialog. The control accepts class names only. It is bound to `PsiClassPanel`. +This is a one-line editor with a browse button that opens the standard class selection dialog. +The control accepts class names only. +It is bound to `PsiClassPanel`. ![PsiClassControl](img/xml_dom_api/psiclasscontrol.gif) ##### PsiTypeControl -This is almost the same as PsiClassControl, but allows entering not only class names, but also Java primitive types and even arrays. It is bound to `PsiTypePanel`. +This is almost the same as PsiClassControl, but allows entering not only class names, but also Java primitive types and even arrays. +It is bound to `PsiTypePanel`. ### Collection Control -There is a special table component where each row represents one collection child. It's called `DomCollectionControl`, where `T` is your collection element type. To function properly, it needs `DomElement` (parent of the collection), some description of the collection (sub-tag name or a `DomCollectionChildDescription` from DOM reflection), and a `ColumnInfo` array. This can be passed to the constructor, or can be created in a `DomCollectionControl` inheritor, in an overriden method `createColumnInfos()`. +There is a special table component where each row represents one collection child. +It's called `DomCollectionControl`, where `T` is your collection element type. +To function properly, it needs `DomElement` (parent of the collection), some description of the collection (sub-tag name or a `DomCollectionChildDescription` from DOM reflection), and a `ColumnInfo` array. +This can be passed to the constructor, or can be created in a `DomCollectionControl` inheritor, in an overriden method `createColumnInfos()`. -What is a column info? It's just a somewhat more comfortable way to work with the table model. It uses Java 5 generics and is more object-oriented. So, it's named `ColumnInfo`, where `Item` is a type variable corresponding to the type of elements in the collection, and `Aspect` is a type variable corresponding to this particular column information type: `String`, `PsiClass`, `Boolean`, etc. The basic things that a column knows are: column name, column class, reading value (Aspect `valueOf(Item)`), writing value (`setValue(Item item, Aspect aspect)`), cell renderer (`getRenderer(Item)`), cell "editability" (`isCellEditable(Item)`), cell editor (`getEditor(Item)`), etc. +What is a column info? It's just a somewhat more comfortable way to work with the table model. +It uses Java 5 generics and is more object-oriented. +So, it's named `ColumnInfo`, where `Item` is a type variable corresponding to the type of elements in the collection, and `Aspect` is a type variable corresponding to this particular column information type: `String`, `PsiClass`, `Boolean`, etc. +The basic things that a column knows are: column name, column class, reading value (Aspect `valueOf(Item)`), writing value (`setValue(Item item, Aspect aspect)`), cell renderer (`getRenderer(Item)`), cell "editability" (`isCellEditable(Item)`), cell editor (`getEditor(Item)`), etc. -There are a lot of predefined column infos, so you'll probably never create a new one. +There are a lot of predefined column infos, so you'll probably never create a new one. -First, if a collection child is a `GenericDomValue`, it's usually convenient to edit it directly in the table. For this, you may need one of the following classes: `StringColumnInfo`, `BooleanColumnInfo`, or more generic `GenericValueColumnInfo`. But such collections are encountered very rarely. +First, if a collection child is a `GenericDomValue`, it's usually convenient to edit it directly in the table. +For this, you may need one of the following classes: `StringColumnInfo`, `BooleanColumnInfo`, or more generic `GenericValueColumnInfo`. +But such collections are encountered very rarely. -A more common case is when a collection element is more complex and has several `GenericDomValue` children. Then one may create a column for each of those children. The appropriate column info is `ChildGenericValueColumnInfo`. It will ask you for a `DomFixedChildDescription` (one more thing from DOM reflection), a renderer and an editor — nothing else. So, the main things left to customize are the renderer and the editor. +A more common case is when a collection element is more complex and has several `GenericDomValue` children. +Then one may create a column for each of those children. +The appropriate column info is `ChildGenericValueColumnInfo`. +It will ask you for a `DomFixedChildDescription` (one more thing from DOM reflection), a renderer and an editor — nothing else. +So, the main things left to customize are the renderer and the editor. -As for the renderer, there are two main choices: `DefaultTableCellRenderer`, and IntelliJ Platform's `BooleanTableCellRenderer`. Editors are more complicated, but they closely resemble simple DOM controls. +As for the renderer, there are two main choices: `DefaultTableCellRenderer`, and IntelliJ Platform's `BooleanTableCellRenderer`. +Editors are more complicated, but they closely resemble simple DOM controls. `BooleanTableCellEditor`, `DefaultCellEditor(JTextField)`, `ComboTableCellEditor`, etc. `DomUIFactory.createCellEditor()` will create any of them automatically (including the editor for `PsiClass`), so that you won't need to think about which one to select every time. -Collection control is a complex control, so it's bound to a complex Swing component. It's called [`DomTableView`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/DomTableView.java). It has a toolbar (you can override `DomTableView.getToolbarPosition()` to customize its location), with Add and Delete buttons. If you want, you may specify custom addition actions in `DomCollectionControl.createAdditionActions()` (it's recommended to extend `ControlAddAction`). If there is only one addition action, it will be invoked after pressing the Add button; if there are many, then a popup menu will be displayed. To change the removal policy, override the `DomCollectionControl.doRemove(List)` method. +Collection control is a complex control, so it's bound to a complex Swing component. +It's called [`DomTableView`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/DomTableView.java). +It has a toolbar (you can override `DomTableView.getToolbarPosition()` to customize its location), with Add and Delete buttons. +If you want, you may specify custom addition actions in `DomCollectionControl.createAdditionActions()` (it's recommended to extend `ControlAddAction`). +If there is only one addition action, it will be invoked after pressing the Add button; if there are many, then a popup menu will be displayed. +To change the removal policy, override the `DomCollectionControl.doRemove(List)` method. -The toolbar may also have an Edit button, if you specify that `DomCollectionControl.isEditable()`. To add a behavior to this button, override `DomCollectionControl.doEdit(T)`. There can also be a Help button, if you pass a non-null String _helpId_ parameter while constructing your `DomTableView`. +The toolbar may also have an Edit button, if you specify that `DomCollectionControl.isEditable()`. +To add a behavior to this button, override `DomCollectionControl.doEdit(T)`. +There can also be a Help button, if you pass a non-null String _helpId_ parameter while constructing your `DomTableView`. If there are no items in the collection, `DomTableView` may display a special text (`DomTableView.getEmptyPaneText()`), instead of an empty table. -You can add your own popup menu to the control. Call the `DomTableView.installPopup()` method after construction, and pass a `DefaultActionGroup` with your popup actions. +You can add your own popup menu to the control. +Call the `DomTableView.installPopup()` method after construction, and pass a `DefaultActionGroup` with your popup actions. -Tables can have single or multiple (default) row selection. If you want to change this behavior, override `DomTableView.allowMultipleRowsSelection()`. +Tables can have single or multiple (default) row selection. +If you want to change this behavior, override `DomTableView.allowMultipleRowsSelection()`. ![CollectionControl](img/xml_dom_api/collectioncontrol.gif) ### UI Organization -The easiest way to create a DOM-based UI form is to extend the [`BasicDomElementComponent`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/BasicDomElementComponent.java) class. This will require you to pass some DOM element to the constructor. Then you bind an IntelliJ IDEA GUI Designer form to your subclass and design a beautiful form there. You will surely want to bind some controls to DOM UI, in which case you should of course ensure that they have right types. Finally, you should create some DOM controls in class' constructor and bind them. But you can create controls and bind them to the `DomElement`'s children — `GenericDomValue`'s automatically. +The easiest way to create a DOM-based UI form is to extend the [`BasicDomElementComponent`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/BasicDomElementComponent.java) class. +This will require you to pass some DOM element to the constructor. +Then you bind an IntelliJ IDEA GUI Designer form to your subclass and design a beautiful form there. +You will surely want to bind some controls to DOM UI, in which case you should of course ensure that they have right types. +Finally, you should create some DOM controls in class' constructor and bind them. +But you can create controls and bind them to the `DomElement`'s children — `GenericDomValue`'s automatically. -Just name your components properly and call the `bindProperties()` method in the constructor. The field names should correspond to the getter names for the element's children. They may also be prefixed with "my". Imagine that you have such DOM interface: +Just name your components properly and call the `bindProperties()` method in the constructor. +The field names should correspond to the getter names for the element's children. +They may also be prefixed with "my". +Imagine that you have such DOM interface: ```java public interface Converter extends DomElement { @@ -532,10 +771,15 @@ public class ConverterComponent extends BasicDomElementComponent { All the fields here are now bound to controls in a GUI form. -Very often you'll have to create your own file editor. Then, to use all the binding and undo functionality, it's suggested to inherit your [`FileEditorProvider`](upsource:///platform/analysis-api/src/com/intellij/openapi/fileEditor/FileEditorProvider.java) from [`PerspectiveFileEditorProvider`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/PerspectiveFileEditorProvider.java), create an instance of [`DomFileEditor`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/DomFileEditor.java) there, and pass a [`BasicDomElementComponent`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/BasicDomElementComponent.java). To easily create an editor with a caption at the top, like in our EJB and JSF, you may use the static method `DomFileEditor.createDomFileEditor()`. `DomFileEditor` automatically listens to all changes in the document corresponding to the given DOM element, and therefore refreshes your component on undo. If you want to listen to changes in additional documents, use the methods `addWatchedDocument()`, `removeWatchedDocument()`, `addWatchedElement()`, `removeWatchedElement()` in `DomFileEditor`. +Very often you'll have to create your own file editor. +Then, to use all the binding and undo functionality, it's suggested to inherit your [`FileEditorProvider`](upsource:///platform/analysis-api/src/com/intellij/openapi/fileEditor/FileEditorProvider.java) from [`PerspectiveFileEditorProvider`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/PerspectiveFileEditorProvider.java), create an instance of [`DomFileEditor`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/DomFileEditor.java) there, and pass a [`BasicDomElementComponent`](upsource:///xml/dom-openapi/src/com/intellij/util/xml/ui/BasicDomElementComponent.java). +To easily create an editor with a caption at the top, like in our EJB and JSF, you may use the static method `DomFileEditor.createDomFileEditor()`. `DomFileEditor` automatically listens to all changes in the document corresponding to the given DOM element, and therefore refreshes your component on undo. +If you want to listen to changes in additional documents, use the methods `addWatchedDocument()`, `removeWatchedDocument()`, `addWatchedElement()`, `removeWatchedElement()` in `DomFileEditor`. ## Conclusion -Thank you for your time and attention. We hope you've found this article really useful. You are welcome to post your questions and comments to our [Open API and Plugin Development Forum](https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development). +Thank you for your time and attention. +We hope you've found this article really useful. +You are welcome to post your questions and comments to our [Open API and Plugin Development Forum](https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development). ### Further Material The following bundled open-source plugins make (heavy) use of DOM: @@ -545,4 +789,3 @@ The following bundled open-source plugins make (heavy) use of DOM: - [Plugin DevKit](upsource:///plugins/devkit/devkit-core) - [Maven](upsource:///plugins/maven) - [Struts 2](https://github.com/JetBrains/intellij-plugins/tree/master/struts2) (Ultimate Edition) - diff --git a/reference_guide/intellij_artifacts.md b/reference_guide/intellij_artifacts.md index 8d5138c38..ec361e0cc 100644 --- a/reference_guide/intellij_artifacts.md +++ b/reference_guide/intellij_artifacts.md @@ -5,51 +5,51 @@ title: IntelliJ Platform Artifacts Repositories > **WARNING** When using additional repositories, make sure to use HTTPS always. -JetBrains maintains public repositories that host artifacts related to the IntelliJ Platform, such as binaries and source code. These -repositories make artifacts more accessible for plugin developers. +JetBrains maintains public repositories that host artifacts related to the IntelliJ Platform, such as binaries and source code. +These repositories make artifacts more accessible for plugin developers. The IntelliJ Platform artifacts repositories are: * [Releases repository](https://www.jetbrains.com/intellij-repository/releases/) for release versions by [build number](/basics/getting_started/build_number_ranges.md). -* [Snapshots repository](https://www.jetbrains.com/intellij-repository/snapshots/) for _BRANCH#-EAP-SNAPSHOT_, _EAP-CANDIDATE-SNAPSHOT_, _LATEST-EAP-SNAPSHOT_, and the _EAP-SNAPSHOT_. +* [Snapshots repository](https://www.jetbrains.com/intellij-repository/snapshots/) for _BRANCH#-EAP-SNAPSHOT_, _EAP-CANDIDATE-SNAPSHOT_, _LATEST-EAP-SNAPSHOT_, and the _EAP-SNAPSHOT_. -See the [Maven coordinates](#specify-the-maven-coordinates-for-the-artifact) section for details about specifying these artifacts. +See the [Maven coordinates](#specify-the-maven-coordinates-for-the-artifact) section for details about specifying these artifacts. Both the Releases and Snapshots repositories have two types of content: -* Binary and source code artifacts for cross-platform, ZIP distributions of IntelliJ Platform-based IDEs, such as IntelliJ IDEA, CLion, Rider, and MPS. - These artifacts are _not intended_ to be accessed directly from a plugin project's `build.gradle` file. +* Binary and source code artifacts for cross-platform, ZIP distributions of IntelliJ Platform-based IDEs, such as IntelliJ IDEA, CLion, Rider, and MPS. + These artifacts are _not intended_ to be accessed directly from a plugin project's `build.gradle` file. The `gradle-intellij-plugin` will access them as-needed for a plugin project. -* Artifacts for individual modules from the IntelliJ Platform. +* Artifacts for individual modules from the IntelliJ Platform. These may be downloaded, or accessed directly from a `build.gradle` file, as explained below. - -Artifacts for IntelliJ Platform third-party dependencies are hosted at the [Bintray repository](https://jetbrains.bintray.com/intellij-third-party-dependencies). -A link to this repository should be added to `pom.xml`/`build.gradle` files when individual modules from an IntelliJ Platform artifacts repository are used. + +Artifacts for IntelliJ Platform third-party dependencies are hosted at the [Bintray repository](https://jetbrains.bintray.com/intellij-third-party-dependencies). +A link to this repository should be added to `pom.xml`/`build.gradle` files when individual modules from an IntelliJ Platform artifacts repository are used. ## Using IntelliJ Platform Module Artifacts -IntelliJ Platform module artifacts are utilized by adding information to a project's `build.gradle` file. -More information about [Gradle support](https://www.jetbrains.com/help/idea/gradle.html) is available in the IntelliJ IDEA Help documentation. +IntelliJ Platform module artifacts are utilized by adding information to a project's `build.gradle` file. +More information about [Gradle support](https://www.jetbrains.com/help/idea/gradle.html) is available in the IntelliJ IDEA Help documentation. To setup dependencies on a module there are two types of information needed: 1. Specify the corresponding repository URL for the artifact. -2. Specify the [Maven coordinates](https://maven.apache.org/pom.html#Maven_Coordinates) for the artifact. - -### Specify the Repository URL +2. Specify the [Maven coordinates](https://maven.apache.org/pom.html#Maven_Coordinates) for the artifact. + +### Specify the Repository URL The URL for the desired artifact needs to be added to a Maven or Gradle script: -* For release versions, use `https://www.jetbrains.com/intellij-repository/releases` +* For release versions, use `https://www.jetbrains.com/intellij-repository/releases` * For EAP snapshots, use `https://www.jetbrains.com/intellij-repository/snapshots` -* For dependencies on individual modules from the IntelliJ Platform, also use `https://jetbrains.bintray.com/intellij-third-party-dependencies` +* For dependencies on individual modules from the IntelliJ Platform, also use `https://jetbrains.bintray.com/intellij-third-party-dependencies` ### Specify the Maven Coordinates for the Artifact Describing a desired IntelliJ Platform module artifact is done with Maven coordinates: _groupId_, _artifactId_, and _version_. The Maven coordinates are based on the names of modules. -The _groupId_ for a module is the prefix `com.jetbrains.` concatenated with the first two parts of the module name. -For example, the module `intellij.xml` would have the groupId `com.jetbrains.intellij.xml`. +The _groupId_ for a module is the prefix `com.jetbrains.` concatenated with the first two parts of the module name. +For example, the module `intellij.xml` would have the groupId `com.jetbrains.intellij.xml`. -The _artifactId_ is the second.._n_ parts of the module name separated by "-" characters. +The _artifactId_ is the second.._n_ parts of the module name separated by "-" characters. For example, the module `intellij.xml` would have the artifactId `xml`. -There are some special cases to artifactId names. +There are some special cases to artifactId names. If the second part of the module name is a common group like `platform`, `vcs`, or `cloud`, the second part of the module name is dropped, and the artifactId becomes the third.._n_ parts of the module name, separated by "-" characters. -Portions of the module name expressed in `camelCase` format are divided and used in the artifactId as (all lower case) `camel-case`. +Portions of the module name expressed in `camelCase` format are divided and used in the artifactId as (all lower case) `camel-case`. The table below shows some example module names and their corresponding groupId and artifactId. @@ -62,13 +62,13 @@ The table below shows some example module names and their corresponding groupId |intellij.spring | com.jetbrains.intellij.spring | spring | |intellij.xml.impl | com.jetbrains.intellij.xml | xml-impl | -The artifact _version_ can be specified in one of several ways because each artifact [at the Repository URLs](#specify-the-repository-url) has multiple versions available: +The artifact _version_ can be specified in one of several ways because each artifact [at the Repository URLs](#specify-the-repository-url) has multiple versions available: * Specify release build versions as _MAJOR[.MINOR][.FIX]_. For example `14`, or `14.1`, or `14.1.1` * Snapshot versions are specified as: * The snapshot of the most recent branch build is specified as _BRANCH-EAP-SNAPSHOT_. For example, `193-EAP-SNAPSHOT`. There is only one of this type of build for each branch of each product. * The snapshot of the branch from which the next EAP/release build might be produced is specified as _BRANCH.BUILD-EAP-CANDIDATE-SNAPSHOT_. For example `193.4386-EAP-CANDIDATE-SNAPSHOT`. - There are multiple builds of this type, one for each build in each branch of every product. + There are multiple builds of this type, one for each build in each branch of every product. * The latest snapshot of a product is always specified as _LATEST-EAP-SNAPSHOT_. There is only one build of this type per product, and it is always the same as the _BRANCH-EAP-SNAPSHOT_ for the newest branch of the product. * A snapshot of a branch is specified as _BRANCH.BUILD.FIX-EAP-SNAPSHOT_. For example, `193.4386.10-EAP-SNAPSHOT`. @@ -83,13 +83,13 @@ For example, to specify the `jps-model-serialization` module: ## Gradle Example for an Individual Module from the IntelliJ Platform -This section presents an example of using a Gradle script to incorporate an IntelliJ Platform module and repository in a `build.gradle` file. -The example illustrates declaring the artifact URL, Maven coordinates, and version for the `jps-model-serialization` module artifact. +This section presents an example of using a Gradle script to incorporate an IntelliJ Platform module and repository in a `build.gradle` file. +The example illustrates declaring the artifact URL, Maven coordinates, and version for the `jps-model-serialization` module artifact. There are two parts to the example: the repository and the dependency sections. -### Repositories Section +### Repositories Section This code snippet selects the release repository with the first URL, and repository of IntelliJ Platform dependencies with the second URL. -The second URL is needed because this example selects individual modules. +The second URL is needed because this example selects individual modules. ```groovy repositories { @@ -98,7 +98,7 @@ repositories { } ``` -### Dependencies Section +### Dependencies Section This code snippet specifies the desired module artifacts. ```groovy diff --git a/reference_guide/internal_actions/enabling_internal.md b/reference_guide/internal_actions/enabling_internal.md index c92d0764a..6d3d823d6 100644 --- a/reference_guide/internal_actions/enabling_internal.md +++ b/reference_guide/internal_actions/enabling_internal.md @@ -19,5 +19,3 @@ idea.is.internal=true * Save the `idea.properties` file and restart IntelliJ IDEA. The Internal Actions menu is available in **Tools \| Internal Actions**. - - diff --git a/reference_guide/internal_actions/internal_ui_inspector.md b/reference_guide/internal_actions/internal_ui_inspector.md index 2e8161040..25feddadb 100644 --- a/reference_guide/internal_actions/internal_ui_inspector.md +++ b/reference_guide/internal_actions/internal_ui_inspector.md @@ -13,7 +13,7 @@ If the menu item **Tools \| Internal Actions \| UI \| UI Inspector** is not avai ## Enabling the UI Inspector Before using the _UI Inspector_, it must be enabled by selecting the menu item **Tools \| Internal Actions \| UI \| UI Inspector**. -The enabled state of the _UI Inspector_ is modal; it remains enabled until it is disabled by selecting the _UI Inspector_ menu item again. +The enabled state of the _UI Inspector_ is modal; it remains enabled until it is disabled by selecting the _UI Inspector_ menu item again. ## Using the UI Inspector While enabled, centering the cursor on a UI element and pressing Control/Cmd+Alt when _clicking_ the mouse reveals the properties of the Swing component. @@ -25,7 +25,8 @@ The _UI Inspector_ displays that the icon has the internal path `AllIcons.Action ![Internal Icon Info](img/internal_uii_icon_info.png) ## Additional Properties -Various components used in the IntelliJ Platform expose additional properties. These can be useful to locate the underlying implementation, related Action, etc. +Various components used in the IntelliJ Platform expose additional properties. +These can be useful to locate the underlying implementation, related Action, etc. | Type | Place | Properties | |------|-----------|------------| @@ -36,4 +37,4 @@ Various components used in the IntelliJ Platform expose additional properties. T | [`IntentionAction`/`QuickFix`](/reference_guide/custom_language_support/code_inspections_and_intentions.md) | Popup Menu in Editor | `intention action`/`quick fix` - [`IntentionAction`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java) / [`QuickFix`](upsource:///platform/analysis-api/src/com/intellij/codeInspection/QuickFix.java) implementation | | [`Tree`](/user_interface_components/lists_and_trees.md) | Tree | `treeModelClass` - `javax.swing.tree.TreeModel` implementation | -Custom Swing components can also provide additional properties via [`UiInspectorContextProvider`](upsource:///platform/platform-impl/src/com/intellij/internal/inspector/UiInspectorContextProvider.java) (2020.1 and later). +Custom Swing components can also provide additional properties via [`UiInspectorContextProvider`](upsource:///platform/platform-impl/src/com/intellij/internal/inspector/UiInspectorContextProvider.java) (2020.1 and later). diff --git a/reference_guide/internal_actions/internal_ui_laf_defaults.md b/reference_guide/internal_actions/internal_ui_laf_defaults.md index 87f622b85..a9928ec06 100644 --- a/reference_guide/internal_actions/internal_ui_laf_defaults.md +++ b/reference_guide/internal_actions/internal_ui_laf_defaults.md @@ -7,23 +7,23 @@ redirect_from: The _LaF Defaults_ window provides a key-value pair lookup for UI Controls. -It also allows interactive prototyping of UI Control color changes. +It also allows interactive prototyping of UI Control color changes. If the menu item **Tools \| Internal Actions** is not available in IntelliJ IDEA, then the first step is to [enable internal mode](enabling_internal.md) ## Opening LaF Defaults The _LaF Defaults_ window is opened by selecting the menu item **Tools \| Internal Actions \| UI \| LaF Defaults**. -The _LaF Defaults_ window has two columns representing key-value pairs for UI Controls: +The _LaF Defaults_ window has two columns representing key-value pairs for UI Controls: * The _Name_ column contains the UI Control `key` for each IntelliJ Platform UI element available at runtime. -* The _Value_ column contains the UI Control color `value` for each IntelliJ Platform UI element. +* The _Value_ column contains the UI Control color `value` for each IntelliJ Platform UI element. ## Using the LaF Panel -### Finding UI Controls +### Finding UI Controls The _LaF Defaults_ window is used interactively by entering a UI element type - e.g. `Panel` - in the _Filter_ text box at the top. _LaF Defaults_ shows the list of UI Control names matching the filter. -Clicking on one of the names narrows the information to show only the key-value pair for that UI element: +Clicking on one of the names narrows the information to show only the key-value pair for that UI element: ![LaF Lookup](img/internal_lafd_win.png) @@ -33,7 +33,4 @@ The _Choose Color_ window is displayed. Color changes can be specified as RGB, hexadecimal, or using the color picker. Pressing the _Choose_ button changes the UI Control color immediately. -UI Control colors can be reset using the _Choose Color_ window, or by resetting the [UI Theme](https://www.jetbrains.com/help/idea/settings-appearance.html). - - - +UI Control colors can be reset using the _Choose Color_ window, or by resetting the [UI Theme](https://www.jetbrains.com/help/idea/settings-appearance.html). diff --git a/reference_guide/internal_actions/internal_ui_sub.md b/reference_guide/internal_actions/internal_ui_sub.md index da802ed58..5406576ef 100644 --- a/reference_guide/internal_actions/internal_ui_sub.md +++ b/reference_guide/internal_actions/internal_ui_sub.md @@ -8,6 +8,6 @@ The Internal Actions UI submenu provides IntelliJ Platform plugin developers wit > **TIP** If the menu item **Tools \| Internal Actions** is not available in IntelliJ IDEA, then the first step is to [Enabling Internal Mode](enabling_internal.md) ## The Tools Available on the UI Submenu -Here are some of the tools available on the UI submenu of the Internal Actions menu: -* [UI Inspector](internal_ui_inspector.md) is a tool to get an internal description with the properties of each UI element. -* [LaF Defaults](internal_ui_laf_defaults.md) provides a way to lookup the key-value pair for a UI element, and the ability to prototype the color of UI Controls. \ No newline at end of file +Here are some tools available on the UI submenu of the Internal Actions menu: +* [UI Inspector](internal_ui_inspector.md) is a tool to get an internal description with each UI element's properties. +* [LaF Defaults](internal_ui_laf_defaults.md) provides a way to lookup the key-value pair for a UI element, and the ability to prototype the color of UI Controls. diff --git a/reference_guide/jcef.md b/reference_guide/jcef.md index 0a4051f61..2055488f3 100644 --- a/reference_guide/jcef.md +++ b/reference_guide/jcef.md @@ -3,7 +3,8 @@ title: JCEF - Java Chromium Embedded Framework --- -> **WARNING** JCEF is available since 2020.1 as an **experimental feature**. We plan to deprecate using JavaFX in 3rd party plugins and switch to JCEF in 2020.2. +> **WARNING** JCEF is available since 2020.1 as an **experimental feature**. +> We plan to deprecate using JavaFX in 3rd party plugins and switch to JCEF in 2020.2. > To continue using JavaFX in 2020.2 or later, an explicit dependency on [JavaFX Runtime for Plugins](https://plugins.jetbrains.com/plugin/14250-javafx-runtime-for-plugins) must be added. > Please see also blog post [JavaFX and JCEF in the IntelliJ Platform](https://blog.jetbrains.com/platform/2020/07/javafx-and-jcef-in-the-intellij-platform/) for summary of plans. @@ -12,23 +13,25 @@ JCEF is a Java port of [CEF](https://bitbucket.org/chromiumembedded/cef/wiki/Hom Embedding of the browser component inside the IDE allows amongst others: - rendering HTML content -- previewing generated HTML (e.g., from Markdown) +- previewing generated HTML (e.g., from Markdown) -## Enabling JCEF +## Enabling JCEF > **NOTE** JCEF is available and enabled by default in 2020.2. - + Using JCEF requires using a dedicated JetBrains Runtime, please follow these [installation instructions](https://youtrack.jetbrains.com/issue/IDEA-231833#focus=streamItem-27-3993099.0-0) on how to obtain and activate it in your IDE. Enable `ide.browser.jcef.enabled` in Registry dialog (invoke **Help \| Find Action** and type "Registry") and restart the IDE for changes to take effect. ## Debugging -The [Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/), embedded into JCEF, can be used as a debugging and profiling tool. It’s active by default, so that a Chrome DevTools client can attach to it via the default port number - `9222`. +The [Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/), embedded into JCEF, can be used as a debugging and profiling tool. +It’s active by default, so that a Chrome DevTools client can attach to it via the default port number - `9222`. The port number can be configured with the following registry key: ``` ide.browser.jcef.debug.port=9222 ``` -JavaScript debugger in IntelliJ IDEA Ultimate can thus be used to debug JavaScript code running in the IDE via the Chrome DevTools. Use the _Attach to Node.js/Chrome_ configurations with a proper port number. +JavaScript debugger in IntelliJ IDEA Ultimate can thus be used to debug JavaScript code running in the IDE via the Chrome DevTools. +Use the _Attach to Node.js/Chrome_ configurations with a proper port number. Also, JCEF provides a default Chrome DevTools front-end (similar to the one in the Chrome browser) that can be opened from the JCEF’s browser component context menu via **Open DevTools** (the menu item is available in [internal mode](/reference_guide/internal_actions/enabling_internal.md) only). @@ -58,10 +61,10 @@ Before using JCEF, `JBCefApp.isSupported()` check must be called: if (!JBCefApp.isSupported()) { // Fallback to an alternative browser-less solution return; - } + } // Use JCEF -``` +``` JCEF can be unsupported when: - It’s not available in the IDE runtime (the IDE is started with an alternative OpenJDK). @@ -71,8 +74,10 @@ To avoid the above problems, the IDE should be run with the bundled JBR. ### [`com.intellij.ui.jcef.JBCefClient`](upsource:///platform/platform-api/src/com/intellij/ui/jcef/JBCefClient.java) -Is tied to every browser component explicitly or implicitly. Used for adding handlers to the associated browser. -The same instance can be shared among multiple browsers. It is up to the developer to use a shared or per-browser instance, depending on the handlers' logic. +Is tied to every browser component explicitly or implicitly. +Used for adding handlers to the associated browser. +The same instance can be shared among multiple browsers. +It is up to the developer to use a shared or per-browser instance, depending on the handlers' logic. If a client was created explicitly, it should be disposed by the developer; otherwise, it is disposed automatically following the associated browser instance disposal. ### [`com.intellij.ui.jcef.JBCefBrowser`](upsource:///platform/platform-api/src/com/intellij/ui/jcef/JBCefBrowser.java) @@ -95,7 +100,8 @@ For executing JS code and callbacks (see below), use the wrapped `CefBrowser` in getCefBrowser().executeJavaScript(String code, String url, int line); ``` -By default, `JBCefBrowser` is created with implicit `JBCefClient` (disposed automatically). It is possible to pass your own `JBCefClient` (disposed by the developer). +By default, `JBCefBrowser` is created with implicit `JBCefClient` (disposed automatically). +It is possible to pass your own `JBCefClient` (disposed by the developer). For accessing: @@ -114,21 +120,23 @@ The simplest way to add a browser component to your UI: Provides JS query callback mechanism. -There’s no direct access to JS DOM from Java (like in JavaFX WebView, see also [this issue](https://youtrack.jetbrains.com/issue/JBR-2046)). Still, JCEF provides an asynchronous way to communicate to JS. +There’s no direct access to JS DOM from Java (like in JavaFX WebView, see also [this issue](https://youtrack.jetbrains.com/issue/JBR-2046)). +Still, JCEF provides an asynchronous way to communicate to JS. -It’s simpler to illustrate it by an example. Say, we want to open a link in an external browser (see it in [`MarkdownJCEFHtmlPanel`](upsource:///plugins/markdown/src/org/intellij/plugins/markdown/ui/preview/jcef/MarkdownJCEFHtmlPanel.java)): +It’s simpler to illustrate it by an example. +Say we want to open a link in an external browser, and see it in [`MarkdownJCEFHtmlPanel`](upsource:///plugins/markdown/src/org/intellij/plugins/markdown/ui/preview/jcef/MarkdownJCEFHtmlPanel.java): ```java // Create a JS query instance final JBCefJSQuery myJSQueryOpenInBrowser = JBCefJSQuery.create(myJBCefBrowser); - + // Add a query handler myJSQueryOpenInBrowser.addHandler((link) -> { MarkdownAccessor.getSafeOpenerAccessor().openLink(link); return null; // can respond back to JS with JBCefJSQuery.Response }); - + // Inject the query callback into JS myCefBrowser.executeJavaScript( "window.JavaPanelBridge = {" + @@ -137,7 +145,7 @@ It’s simpler to illustrate it by an example. Say, we want to open a link in an "}" + "};", getCefBrowser().getURL(), 0); - + // Dispose the query when necessary Disposer.dispose(myJSQueryOpenInBrowser); ``` diff --git a/reference_guide/localization_guide.md b/reference_guide/localization_guide.md index f13bdd651..89d76071e 100644 --- a/reference_guide/localization_guide.md +++ b/reference_guide/localization_guide.md @@ -20,40 +20,37 @@ In order to enable multiple localizations per installation without localization ## Content and Layout of resources_en.jar -Property files usually contain messages, menu items, dialog labels texts etc. +Property files usually contain messages, menu items, dialog labels texts etc. For every such file localized jar should contain translated version that is placed to exactly the same path relative to the jar root and has exactly the same name as original file plus locale identifier. For example ***messages/ActionsBundle.properties*** file from ***resources_en.jar*** should have its translated version ***messages/ActionsBundle_ja.properties*** file in ***resources_ja.jar***. All property files should be ASCII encoded with *\uXXXX* sequences used for characters that have no their representation in ASCII range. -See -[native2ascii](https://docs.oracle.com/javase/7/docs/technotes/tools/solaris/native2ascii.html) -tool for more details. +See [native2ascii](https://docs.oracle.com/javase/7/docs/technotes/tools/solaris/native2ascii.html) tool for more details. Property values mostly follow MessageFormat rules. -> **NOTE** Due to historic reasons main menu, toolbar, popup menus and other actions have their mnemonic char prefixed with `\_` (underscore) char while all other mnemonics like those for checkboxes, buttons etc. use `&` (ampersand) sign for the same purpose. Moreover one can encounter `&&` (double ampersand) in some places, which denote alternative mnemonic to be used under MacOS X (mnemonics mapped to `U`, `I`, `O`, `N` chars won't work there). Generally, use the same mnemonic denotation used in original property value and everything will be OK. +> **NOTE** Due to historic reasons main menu, toolbar, popup menus and other actions have their mnemonic char prefixed with `\_` (underscore) char while all other mnemonics like those for checkboxes, buttons etc. use `&` (ampersand) sign for the same purpose. +> Moreover one can encounter `&&` (double ampersand) in some places, which denote alternative mnemonic to be used under MacOS X (mnemonics mapped to `U`, `I`, `O`, `N` chars won't work there). +> Generally, use the same mnemonic denotation used in the original property value and everything will be OK. ## Components Location -* **Inspection descriptions** appear in Settings|Errors and represent short information about what each of the inspection tools is intended to do. -Each description is represented by single html file under ***/inspectionDescriptions/*** folder that should be encoded in UTF-8 encoding. -Localized versions should be stored in folder suffixed with locale instead. For instance ***/inspectionDescriptions/CanBeFinal.html*** from ***resources_en.jar*** translation should be placed in ***/inspectionDescriptions_ja/CanBeFinal.html*** in ***resources_ja.jar***. - -* **Intention descriptions and samples** are very similar to inspection descriptions but the layout is a bit more advanced. -Every intention has a bunch of files located in the folder named after intention's short name in /intentionDescriptions/. -These files include description.html, which holds description similar to inspection one plus a couple of template files demonstrating what the intention will do on a sample. -Those templates are optional to translate. Similar to inspection descriptions whole intentionDescriptions folder should be suffixed with locale identifier. -For instance ***/intentionDescriptions/AddOnDemandStaticImportAction/description.html*** translation should be placed in ***/intentionDescriptions_ja/AddOnDemandStaticImportAction/description.html***. -All the HTML files should be UTF-8 encoded. - -* **Tips of the day** follow the same pattern inspections and intentions do. -For instance translation of ***/tips/AdaptiveWelcome.html*** goes to ***/tips_ja/AdaptiveWelcome.html***. -The only thing special about tips is they use special pattern for denoting shortcuts like *EnterAction*; -will be replaced to keystroke mapped to *EnterAction* in currently used keymap at run-time. -So please make sure you leave such sequences intact while translating. -Remember UTF-8 encoding. - -* **File templates** again go the same way (if at all should be translated). -***/fileTemplates/Singleton.java.ft*** goes to ***/fileTemplates_ja/Singleton.java.ft***. +* **Inspection descriptions** appear in Settings|Errors and represent short information about what each of the inspection tools is intended to do. + Each description is represented by single html file under ***/inspectionDescriptions/*** folder that should be encoded in UTF-8 encoding. + Localized versions should be stored in folder suffixed with locale instead. + For instance ***/inspectionDescriptions/CanBeFinal.html*** from ***resources_en.jar*** translation should be placed in ***/inspectionDescriptions_ja/CanBeFinal.html*** in ***resources_ja.jar***. +* **Intention descriptions and samples** are very similar to inspection descriptions but the layout is a bit more advanced. + Every intention has a bunch of files located in the folder named after intention's short name in /intentionDescriptions/. + These files include description.html, which holds description similar to inspection one plus a couple of template files demonstrating what the intention will do on a sample. + Those templates are optional to translate. + Similar to inspection descriptions whole intentionDescriptions folder should be suffixed with locale identifier. + For instance ***/intentionDescriptions/AddOnDemandStaticImportAction/description.html*** translation should be placed in ***/intentionDescriptions_ja/AddOnDemandStaticImportAction/description.html***. + All the HTML files should be UTF-8 encoded. +* **Tips of the day** follow the same pattern inspections and intentions do. + For instance translation of ***/tips/AdaptiveWelcome.html*** goes to ***/tips_ja/AdaptiveWelcome.html***. + The only thing special about tips is they use special pattern for denoting shortcuts like *EnterAction*; will be replaced to keystroke mapped to *EnterAction* in currently used keymap at run-time. + So please make sure you leave such sequences intact while translating. + Remember UTF-8 encoding. +* **File templates** again go the same way (if at all should be translated). + ***/fileTemplates/Singleton.java.ft*** goes to ***/fileTemplates_ja/Singleton.java.ft***. Following Sun rules for property bundles whenever certain resource cannot be found in localized version its default version from ***resources_en.jar*** will be used instead. - diff --git a/reference_guide/messaging_infrastructure.md b/reference_guide/messaging_infrastructure.md index b836611c1..75e2d4f36 100644 --- a/reference_guide/messaging_infrastructure.md +++ b/reference_guide/messaging_infrastructure.md @@ -5,13 +5,12 @@ title: Messaging Infrastructure ## Purpose -The purpose of this document is to introduce the messaging infrastructure available in the IntelliJ Platform to developers and plugin writers. It is intended to answer why, when and how to use it. +The purpose of this document is to introduce the messaging infrastructure available in the IntelliJ Platform to developers and plugin writers. +It is intended to answer why, when and how to use it. ## Rationale -So, what is messaging in the IntelliJ Platform and why do we need it? Basically, its implementation of -[Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern) -that provides additional features like _broadcasting on hierarchy_ and special _nested events_ processing (_nested event_ here is a situation when new event is fired (directly or indirectly) from the callback of another event). +So, what is messaging in the IntelliJ Platform and why do we need it? Basically, its implementation of [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern) that provides additional features like _broadcasting on hierarchy_ and special _nested events_ processing (_nested event_ here is a situation when new event is fired (directly or indirectly) from the callback of another event). ## Design @@ -19,18 +18,22 @@ Here are the main components of the messaging API. ### Topic -This class serves as an endpoint at the messaging infrastructure. I.e. clients are allowed to subscribe to the topic within particular bus and to send messages to particular topic within particular bus. +This class serves as an endpoint at the messaging infrastructure. +I.e., clients are allowed to subscribe to a specific topic within a bus and send messages to that topic within that particular bus. ![Topic](img/topic.svg) -* *display name* just a human-readable name used for logging/monitoring purposes; -* *broadcast direction* will be explained in details at Broadcasting. Default value is *TO\_CHILDREN*; -* *listener class* that is a business interface for particular topic. -Subscribers register implementation of this interface at the messaging infrastructure and publishers may later retrieve object that conforms (IS-A) to it and call any method defined there. Messaging infrastructure takes care on dispatching that to all subscribers of the topic, i.e. the same method with the same arguments will be called on the registered callbacks; +* *display name* just a human-readable name used for logging/monitoring purposes; +* *broadcast direction* will be explained in details at Broadcasting. Default value is *TO\_CHILDREN*; +* *listener class* that is a business interface for particular topic. + Subscribers register an implementation of this interface at the messaging infrastructure. + Publishers later retrieve objects that conform to the interface (IS-A) and call any methods defined on those implementations. + The messaging infrastructure takes care of dispatching the message to all subscribers of the topic by calling the same method with the same arguments on the registered implementation callbacks; ### Message Bus -Is the core of the messaging system. Is used at the following scenarios: +Is the core of the messaging system. +Is used at the following scenarios: ![Bus](img/bus.png) @@ -40,17 +43,12 @@ Manages all subscriptions for particular client within particular bus. ![Connection](img/connection.svg) -* keeps number of *topic handler* mappings (callbacks to invoke when message for the target topic is received) -*Note*: not more than one handler per-topic within the same connection is allowed; - -* it's possible to specify *default handler* and subscribe to the target topic without explicitly provided callback. -Connection will use that *default handler* when storing *(topic-handler)* mapping; - -* it's possible to explicitly release acquired resources (*disconnect()* method). -Also it can be plugged to standard semi-automatic disposing -( -[`Disposable`](upsource:///platform/util/src/com/intellij/openapi/Disposable.java) -); +* keeps number of *topic handler* mappings (callbacks to invoke when message for the target topic is received) + *Note*: not more than one handler per-topic within the same connection is allowed; +* it's possible to specify *default handler* and subscribe to the target topic without explicitly provided callback. + Connection will use that *default handler* when storing *(topic-handler)* mapping; +* it's possible to explicitly release acquired resources (*disconnect()* method). + Also it can be plugged to standard semi-automatic disposing ([`Disposable`](upsource:///platform/util/src/com/intellij/openapi/Disposable.java)); ### Putting Altogether @@ -107,21 +105,15 @@ public void doChange(Context context) { *Existing resources* -* *MessageBus* instances are available via -[`ComponentManager.getMessageBus()`](upsource:///platform/extensions/src/com/intellij/openapi/components/ComponentManager.java) -(many standard interfaces implement it, e.g. -[`Application`](upsource:///platform/core-api/src/com/intellij/openapi/application/Application.java), -[`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java); - -* number of public topics are used by the *IntelliJ Platform*, e.g. -[`AppTopics`](upsource:///platform/platform-api/src/com/intellij/AppTopics.java), -[`ProjectTopics`](upsource:///platform/projectModel-api/src/com/intellij/ProjectTopics.java) -etc. -So, it's possible to subscribe to them in order to receive information about the processing; +* *MessageBus* instances are available via [`ComponentManager.getMessageBus()`](upsource:///platform/extensions/src/com/intellij/openapi/components/ComponentManager.java) + Many standard interfaces implement a message bus, e.g., [`Application`](upsource:///platform/core-api/src/com/intellij/openapi/application/Application.java) and [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java). +* A number of public topics are used by the *IntelliJ Platform*, e.g., [`AppTopics`](upsource:///platform/platform-api/src/com/intellij/AppTopics.java), [`ProjectTopics`](upsource:///platform/projectModel-api/src/com/intellij/ProjectTopics.java), etc. + So, it's possible to subscribe to them in order to receive information about the processing; ## Broadcasting -Message buses can be organised into hierarchies. Moreover, the *IntelliJ Platform* has them already: +Message buses can be organised into hierarchies. +Moreover, the *IntelliJ Platform* has them already: ![Standard hierarchy](img/standard_hierarchy.svg) @@ -134,28 +126,26 @@ That allows to notify subscribers registered in one message bus on messages sent Here we have a simple hierarchy (*application bus* is a parent of *project bus*) with three subscribers for the same topic. We get the following if *topic1* defines broadcast direction as *TO\_CHILDREN*: -1. A message is sent to *topic1* via *application bus*; -2. *handler1* is notified about the message; -3. The message is delivered to the subscribers of the same topic within *project bus* (*handler2* and *handler3*); +1. A message is sent to *topic1* via *application bus*; +2. *handler1* is notified about the message; +3. The message is delivered to the subscribers of the same topic within *project bus* (*handler2* and *handler3*); *Benefits* We don't need to bother with memory management of subscribers that are bound to child buses but interested in parent bus-level events. -Consider the example above we may want to have project-specific functionality that reacts to the application-level events. +Consider the example above we may want to have project-specific functionality that reacts to the application-level events. All we need to do is to subscribe to the target topic within the *project bus*. -No hard reference to the project-level subscriber will be stored at application-level then, -i.e. we just avoided memory leak on project re-opening. +No hard reference to the project-level subscriber will be stored at application-level then, i.e., we just avoided memory leak on project re-opening. *Options* -Broadcast configuration is defined per-topic. Following options are available: +Broadcast configuration is defined per-topic. +The following options are available: -* _TO\_CHILDREN_ (default); - -* _NONE_; - -* _TO\_PARENT_; +* TO\_CHILDREN_ (default); +* _NONE_; +* _TO\_PARENT_; ## Nested Messages @@ -170,35 +160,27 @@ Suppose we have the following configuration: Let's see what happens if someone sends a message to the target topic: -* _message1_ is sent; - -* _handler1_ receives _message1_ and sends _message2_ to the same topic; - -* _handler2_ receives _message1_; - -* _handler2_ receives _message2_; - -* _handler1_ receives _message2_; +* _message1_ is sent; +* _handler1_ receives _message1_ and sends _message2_ to the same topic; +* _handler2_ receives _message1_; +* _handler2_ receives _message2_; +* _handler1_ receives _message2_; ## Tips'n'tricks ### Relief Listeners Management -Messaging infrastructure is very light-weight, so, it's possible to reuse it at local sub-systems in order to relief -[Observers](https://en.wikipedia.org/wiki/Observer_pattern) construction. Let's see what is necessary to do then: +Messaging infrastructure is very light-weight, so, it's possible to reuse it at local sub-systems in order to relieve [Observers](https://en.wikipedia.org/wiki/Observer_pattern) construction. +Let's see what is necessary to do then: 1. Define business interface to work with; - 2. Create shared message bus and topic that uses the interface above (_shared_ here means that either _subject_ or _observers_ know about them); Let's compare that with a manual implementation: 1. Define listener interface (business interface); - 2. Provide reference to the _subject_ to all interested listeners; - 3. Add listeners storage and listeners management methods (add/remove) to the _subject_; - 4. Manually iterate all listeners and call target callback in all places where new event is fired; ### Avoid Shared Data Modification from Subscribers @@ -209,24 +191,20 @@ We had a problem in a situation when two subscribers tried to modify the same do The thing is that every document change is performed by the following scenario: 1. _before change_ event is sent to all document listeners and some of them publish new messages during that; - -2. actual change is performed; - -3. _after change_ event is sent to all document listeners; +2. actual change is performed; +3. _after change_ event is sent to all document listeners; We had the following then: -1. _message1_ is sent to the topic with two subscribers; -2. _message1_ is queued for both subscribers; -3. _message1_ delivery starts; -4. _subscriber1_ receives _message1_; -5. _subscriber1_ issues document modification request at particular range (e.g. _document.delete(startOffset, endOffset)_); -6. _before change_ notification is sent to the document listeners; -7. _message2_ is sent by one of the standard document listeners to another topic within the same message bus during _before change_ processing; -8. the bus tries to deliver all pending messages before queuing _message2_; -9. _subscriber2_ receives _message1_ and also modifies a document; -10. the call stack is unwinded and _actual change_ phase of document modification operation requested by _subscriber1_ begins; +1. _message1_ is sent to the topic with two subscribers; +2. _message1_ is queued for both subscribers; +3. _message1_ delivery starts; +4. _subscriber1_ receives _message1_; +5. _subscriber1_ issues document modification request at particular range (e.g. _document.delete(startOffset, endOffset)_); +6. _before change_ notification is sent to the document listeners; +7. _message2_ is sent by one of the standard document listeners to another topic within the same message bus during _before change_ processing; +8. the bus tries to deliver all pending messages before queuing _message2_; +9. _subscriber2_ receives _message1_ and also modifies a document; +10. the call stack is unwinded and _actual change_ phase of document modification operation requested by _subscriber1_ begins; **The problem** is that document range used by _subscriber1_ for initial modification request is invalid if _subscriber2_ has changed document's range before it. - - diff --git a/reference_guide/multiple_carets.md b/reference_guide/multiple_carets.md index fbb7e968d..ec4741623 100644 --- a/reference_guide/multiple_carets.md +++ b/reference_guide/multiple_carets.md @@ -8,34 +8,31 @@ title: Supporting Multiple Carets Support for multiple independent carets has been added to editor implementation in IDEA 13.1. Most editor actions (keyboard navigation, text insertion and deletion, etc.) will be applied to each caret independently. Each caret has its own associated selection, which is a continuous range of document characters (can be empty). -When after some action two or more carets end up in the same visual position, they are merged into a single caret with their associated selections merged into a single one. A similar thing will happen when selections for several carets become overlapped: only one of the carets will remain, and the selections will be merged. +When after some action two or more carets end up in the same visual position, they are merged into a single caret with their associated selections merged into a single one. +A similar thing will happen when selections for several carets become overlapped: only one of the carets will remain, and the selections will be merged. There's a concept of 'primary' caret — the one on which non-multi-caret-aware actions and the actions which need a single-point document context (like code completion) will operate. Currently, the most recent caret is considered the primary one. ## Core Functionality -Core logic related to multi-caret implementation such as accessing currently existing carets, adding and removing carets, is available via -[`CaretModel`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/CaretModel.java) -interface, some changes also have been made in -[`SelectionModel`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/SelectionModel.java) -interface. +Core logic related to multi-caret implementation such as accessing currently existing carets, adding and removing carets, is available via [`CaretModel`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/CaretModel.java) interface, some changes also have been made in [`SelectionModel`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/SelectionModel.java) interface. Check Javadoc of those interfaces for details. Notable changes from old behaviour: -* Previously existing methods in `CaretModel` and `SelectionModel` to query and modify caret and selection positions work by default on the primary caret now. In the context of `CaretModel.runForEachCaret` method though, they operate on the current caret. -So the behaviour of legacy code (not using Caret interface) will depend on the context of its invocation. +* Previously existing methods in `CaretModel` and `SelectionModel` to query and modify caret and selection positions work by default on the primary caret now. + In the context of `CaretModel.runForEachCaret` method though, they operate on the current caret. + So the behaviour of legacy code (not using Caret interface) will depend on the context of its invocation. -* Block selection doesn't exist as a separate concept anymore. -Correspondingly, block-selection-related methods in SelectionModel interface have changed behaviour — `hasBlockSelection()` will always return false, `setBlockSelection()` will create a multi-caret selection equivalent to the requested block selection. -`getBlockSelectionStarts()` and `getBlockSelectionEnds()` methods work in multi-caret state, returning all selected regions. +* Block selection doesn't exist as a separate concept anymore. + Correspondingly, block-selection-related methods in SelectionModel interface have changed behaviour — `hasBlockSelection()` will always return false, `setBlockSelection()` will create a multi-caret selection equivalent to the requested block selection. + `getBlockSelectionStarts()` and `getBlockSelectionEnds()` methods work in multi-caret state, returning all selected regions. ## Editor Actions ### EditorAction and EditorActionHandler -When -[`EditorActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java) is invoked, an additional parameter will be passed to it — a caret instance on which it should operate, or `null` if it's invoked without any caret context. +When [`EditorActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java) is invoked, an additional parameter will be passed to it — a caret instance on which it should operate, or `null` if it's invoked without any caret context. If the handler invokes another handler (delegate handler for the same `actionId` or a completely unrelated handler), that parameter should normally be passed to the delegate unchanged (unless no context caret has been provided to the handler, but it needs to invoke another handler on a specific caret). Of course, the handler can just ignore the caret parameter if its functionality is not related to caret/selection position. @@ -60,30 +57,21 @@ At the moment there's no need to make any changes in the handlers to support mul ### TypedActionHandler, TypedHandlerDelegate -[`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java) -and -[`TypedHandlerDelegate`](upsource:///platform/lang-api/src/com/intellij/codeInsight/editorActions/TypedHandlerDelegate.java) -implementations are invoked only once for each typed character. +[`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java) and [`TypedHandlerDelegate`](upsource:///platform/lang-api/src/com/intellij/codeInsight/editorActions/TypedHandlerDelegate.java) implementations are invoked only once for each typed character. If those handlers need to support multiple carets, they will need to implement that explicitly. [`EditorModificationUtil`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java). `typeInStringAtCaretHonorMultipleCarets()` method is available to do the most common task in this case — inserting the same text into all caret positions and/or moving all carets relatively to their current position. Examples of its usage: -* [`TypedAction`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java). +* [`TypedAction`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java). +* [`XmlGtTypedHandler`](upsource:///xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java). -* [`XmlGtTypedHandler`](upsource:///xml/impl/src/com/intellij/codeInsight/editorActions/XmlGtTypedHandler.java). - -> **NOTE** Starting from version 14, -[`TypedHandlerDelegate`](upsource:///platform/lang-api/src/com/intellij/codeInsight/editorActions/TypedHandlerDelegate.java) -implementations are invoked automatically for each caret. If one wants to implement custom multicaret behaviour on typing, -[`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java) -needs to be provided instead. +> **NOTE** Starting from version 14, [`TypedHandlerDelegate`](upsource:///platform/lang-api/src/com/intellij/codeInsight/editorActions/TypedHandlerDelegate.java) implementations are invoked automatically for each caret. +> If one wants to implement custom multicaret behaviour on typing, [`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java) needs to be provided instead. ## Code Insight Actions -Existing actions inheriting from -[`CodeInsightAction`](upsource:///platform/lang-api/src/com/intellij/codeInsight/actions/CodeInsightAction.java) will work for primary caret only. -To support multiple carets, one should inherit -[`MultiCaretCodeInsightAction`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/actions/MultiCaretCodeInsightAction.java) -instead (each caret might have a different editor and PSI instance, so using the old API is not possible). +Existing actions inheriting from [`CodeInsightAction`](upsource:///platform/lang-api/src/com/intellij/codeInsight/actions/CodeInsightAction.java) will work for primary caret only. +To support multiple carets, one should subclass [`MultiCaretCodeInsightAction`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/actions/MultiCaretCodeInsightAction.java) instead. +Each caret might have a different editor and PSI instance, so using the old API is not possible. diff --git a/reference_guide/performance/performance.md b/reference_guide/performance/performance.md index fea6a4dc1..1077d7882 100644 --- a/reference_guide/performance/performance.md +++ b/reference_guide/performance/performance.md @@ -11,49 +11,44 @@ Avoid `PsiElement` methods which are expensive with deep trees. `getText()` traverses the whole tree under the given element and concatenates strings, consider `textMatches()` instead. -`getTextRange()`, `getContainingFile()`, `getProject()` traverse the tree up to the file, which can be long in very nested trees. If you only need PSI element length, use `getTextLength()`. +`getTextRange()`, `getContainingFile()`, and `getProject()` traverse the tree up to the file, which can be long in very nested trees. +If you only need PSI element length, use `getTextLength()`. File and project often can be computed once per some analysis and then stored in fields or passed via parameters. -Additionally, `getText()`, `getNode()`, `getTextRange()`, etc., all need AST, which can be quite an expensive operation. See below. +Additionally, `getText()`, `getNode()`, `getTextRange()`, etc., all need AST, which can be quite an expensive operation. +See below. -#### Avoid Using Many PSI Trees/Documents +#### Avoid Using Many PSI Trees/Documents Avoid loading too many parsed trees or documents into memory at the same time. Ideally, only AST nodes from files open in the editor should be present in the memory. -Everything else, even if it's needed for resolve/highlighting purposes, can be accessed via PSI interfaces, -but its implementations should [use stubs](/basics/indexing_and_psi_stubs/stub_indexes.md) underneath, which are less CPU- and memory-expensive. +Everything else, even if it's needed for resolve/highlighting purposes, can be accessed via PSI interfaces, but its implementations should [use stubs](/basics/indexing_and_psi_stubs/stub_indexes.md) underneath, which are less CPU- and memory-expensive. -If stubs don't suit your case well (e.g., the information you need is large and/or very rarely needed, or you're -developing a plugin for a language whose PSI you don't control), you can create a [custom index or gist](/basics/indexing_and_psi_stubs.md). +If stubs don't suit your case well (e.g., the information you need is large and/or very rarely needed, or you're developing a plugin for a language whose PSI you don't control), you can create a [custom index or gist](/basics/indexing_and_psi_stubs.md). -You can use [`AstLoadingFilter`](upsource:///platform/core-api/src/com/intellij/util/AstLoadingFilter.java) in production and `PsiManagerEx.setAssertOnFileLoadingFilter()` in tests -to ensure you're not loading AST accidentally. +You can use [`AstLoadingFilter`](upsource:///platform/core-api/src/com/intellij/util/AstLoadingFilter.java) in production and `PsiManagerEx.setAssertOnFileLoadingFilter()` in tests to ensure you're not loading AST accidentally. The same applies to documents: only the ones opened in editors should be loaded. -Usually, you shouldn't need document contents (as most information can be retrieved from PSI). If you nevertheless -need documents, consider saving the information you need to provide in a [custom index or gist](/basics/indexing_and_psi_stubs.md) to get it more cheaply later. -If you still need documents, then at least ensure you load them one by one and don't hold them on -strong references to let GC free the memory as quickly as possible. +Usually, you shouldn't need document contents (as most information can be retrieved from PSI). +If you nevertheless need documents, consider saving the information you need to provide in a [custom index or gist](/basics/indexing_and_psi_stubs.md) to get it more cheaply later. +If you still need documents, then at least ensure you load them one by one and don't hold them on strong references to let GC free the memory as quickly as possible. #### Cache Results of Heavy Computations -These include `PsiElement.getReference(s)`, `PsiReference.resolve()` (and `multiResolve()` and other equivalents), -expression types, type inference results, control flow graphs, etc. +These include `PsiElement.getReference(s)`, `PsiReference.resolve()` (and `multiResolve()` and other equivalents), expression types, type inference results, control flow graphs, etc. Usually, [`CachedValue`](upsource:///platform/core-api/src/com/intellij/psi/util/CachedValue.java) works well. -If the information you cache depends only on a subtree of the current PSI element -(and nothing else: no resolve results or other files), you can cache it in a field in that `PsiElement` and drop the cache -in an override of `ASTDelegatePsiElement.subtreeChanged()`. - +If the information you cache depends only on a subtree of the current PSI element (and nothing else: no resolve results or other files), you can cache it in a field in that `PsiElement` and drop the cache in an override of `ASTDelegatePsiElement.subtreeChanged()`. + ## Improving Indexing Performance #### Avoid Using AST Use lexer information instead of parsed trees if possible. -If impossible, use light AST which doesn't create memory-hungry AST nodes inside, so traversing it might be faster. +If impossible, use light AST which doesn't create memory-hungry AST nodes inside, so traversing it might be faster. Make sure to traverse only the nodes you need to. For stub index, implement [`LightStubBuilder`](upsource:///platform/core-impl/src/com/intellij/psi/stubs/LightStubBuilder.java). @@ -63,8 +58,8 @@ If a custom language contains lazy-parseable elements that never or rarely conta #### Consider Prebuilt Stubs -If your language has a massive standard library, which is mostly the same for all users, you can avoid stub-indexing it -in each installation by providing prebuilt stubs with your distribution. See [`PrebuiltStubsProvider`](upsource:///platform/lang-impl/src/com/intellij/psi/stubs/PrebuiltStubs.kt) extension. +If your language has a massive standard library, which is mostly the same for all users, you can avoid stub-indexing it in each installation by providing prebuilt stubs with your distribution. +See [`PrebuiltStubsProvider`](upsource:///platform/lang-impl/src/com/intellij/psi/stubs/PrebuiltStubs.kt) extension. ## Avoiding UI Freezes @@ -73,19 +68,18 @@ in each installation by providing prebuilt stubs with your distribution. See [`P In particular, don't traverse VFS, parse PSI, resolve references or query `FileBasedIndex`. There are cases when the platform itself invokes such expensive code (e.g., resolve in `AnAction.update()`). -We're trying to eliminate them. Meanwhile, you can try to speed up what you can in your plugin, it'll be beneficial anyway, as it'll also improve -background highlighting performance. +We're trying to eliminate them. +Meanwhile, you can try to speed up what you can in your plugin, it'll be beneficial anyway, as it'll also improve background highlighting performance. -`WriteAction`s currently have to happen on UI thread, so to speed them up, you can try moving as much as possible -out of write action into a preparation step which can be then invoked in background (e.g., using `ReadAction.nonBlocking()`). +`WriteAction`s currently have to happen on UI thread, so to speed them up, you can try moving as much as possible out of write action into a preparation step which can be then invoked in background (e.g., using `ReadAction.nonBlocking()`). -Don't do anything expensive in event listeners. Ideally, you should only clear some caches. -You can also schedule background processing of events, but be prepared that some new events might be delivered -before your background processing starts, and thus the world might have changed by that moment or -even in the middle of background processing. Consider using [`MergingUpdateQueue`](upsource:///platform/platform-api/src/com/intellij/util/ui/update/MergingUpdateQueue.java) and `ReadAction.nonBlocking()` to mitigate these issues. +Don't do anything expensive in event listeners. +Ideally, you should only clear some caches. +You can also schedule background processing of events, but be prepared that some new events might be delivered before your background processing starts, and thus the world might have changed by that moment or even in the middle of background processing. +Consider using [`MergingUpdateQueue`](upsource:///platform/platform-api/src/com/intellij/util/ui/update/MergingUpdateQueue.java) and `ReadAction.nonBlocking()` to mitigate these issues. -Massive batches of VFS events can be pre-processed in background, see [`AsyncFileListener`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/AsyncFileListener.java) (2019.2 or later). +Massive batches of VFS events can be pre-processed in background, see [`AsyncFileListener`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/AsyncFileListener.java) (2019.2 or later). #### Don't block EDT by long non-cancellable `ReadAction`s in background threads -See [General Threading Rules](/basics/architectural_overview/general_threading_rules.md), especially its section on [*Read Action Cancellability*](/basics/architectural_overview/general_threading_rules.md#read-action-cancellability). \ No newline at end of file +See [General Threading Rules](/basics/architectural_overview/general_threading_rules.md), especially its section on [*Read Action Cancellability*](/basics/architectural_overview/general_threading_rules.md#read-action-cancellability). diff --git a/reference_guide/project_model/facet.md b/reference_guide/project_model/facet.md index 78da9b4db..0e8df929e 100644 --- a/reference_guide/project_model/facet.md +++ b/reference_guide/project_model/facet.md @@ -4,7 +4,8 @@ title: Facet A facet represents configuration specific for a particular framework/technology, associated with a module. -A module can have multiple facets. E.g. Spring Framework specific configuration is stored in a Spring facet. +A module can have multiple facets. +E.g. Spring Framework specific configuration is stored in a Spring facet. For more information about facets see [Adding Support for Frameworks and Technologies](https://www.jetbrains.com/help/idea/adding-support-for-frameworks-and-technologies.html) and the help page for the [Facets dialog](https://www.jetbrains.com/help/idea/facet-page.html) in the IntelliJ IDEA Web Help. diff --git a/reference_guide/project_model/library.md b/reference_guide/project_model/library.md index f266a5df8..a74ae99f4 100644 --- a/reference_guide/project_model/library.md +++ b/reference_guide/project_model/library.md @@ -10,8 +10,7 @@ The IntelliJ Platform supports three types of libraries: * **Project Library**: the library classes are visible within the project and the library information is recorded under `.idea/libraries` directory or in the project `.ipr` file. * **Global Library**: the library information is recorded in the `applicationLibraries.xml` file in `/.IntelliJIdea/config/options` directory. Global libraries are similar to project libraries, but are visible for different projects. -For more information about libraries, refer to -[Libraries](https://www.jetbrains.com/help/idea/working-with-libraries.html). +For more information about libraries, refer to [Libraries](https://www.jetbrains.com/help/idea/working-with-libraries.html). A particular type of programmatically defined libraries is [Predefined Libraries](#predefined-libraries). @@ -22,7 +21,7 @@ A particular type of programmatically defined libraries is [Predefined Libraries Package [`libraries`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/libraries) provides functionality for working with project libraries and jars. ### Getting a List of Libraries a Module Depends On -To get the list of libraries that a module depends on, use `OrderEnumerator.forEachLibrary` as follows. +To get the list of libraries that a module depends on, use `OrderEnumerator.forEachLibrary` as follows. ```java final List libraryNames = new ArrayList(); @@ -36,9 +35,8 @@ Messages.showInfoMessage(StringUtil.join(libraryNames, "\n"), "Libraries in Modu This sample code outputs a list of libraries that the given module depends on. ### Getting a List of All Libraries -To manage the lists of application and project libraries, use [`LibraryTable`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/libraries/LibraryTable.java). -The list of application-level library tables is accessed by calling `LibraryTablesRegistrar.getInstance().getLibraryTable()`, -whereas the list of project-level library tables is accessed through `LibraryTablesRegistrar.getInstance().getLibraryTable()`. +To manage the lists of application and project libraries, use [`LibraryTable`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/libraries/LibraryTable.java). +The list of application-level library tables is accessed by calling `LibraryTablesRegistrar.getInstance().getLibraryTable()`, whereas the list of project-level library tables is accessed through `LibraryTablesRegistrar.getInstance().getLibraryTable()`. Once you have a `LibraryTable`, you can get the libraries in it by calling `LibraryTable.getLibraries()`. To get the list of all module libraries defined in a given module, use the following API: @@ -48,8 +46,8 @@ OrderEntryUtil.getModuleLibraries(ModuleRootManager.getInstance(module)); ``` ### Getting the Library Content -[`Library`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/libraries/Library.java) provides the `getUrls()` method you can use to get a list of source roots and classes the library includes. -To clarify, consider the following code snippet: +[`Library`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/libraries/Library.java) provides the `getUrls()` method you can use to get a list of source roots and classes the library includes. +To clarify, consider the following code snippet: ```java StringBuilder roots = new StringBuilder("The " + lib.getName() + " library includes:\n"); @@ -65,7 +63,7 @@ Messages.showInfoMessage(roots.toString(), "Library Info"); ``` ### Creating a Library -To create a library, perform the following steps: +To create a library, perform the following steps: * Get a [write action](../../basics/architectural_overview/general_threading_rules.md#readwrite-lock) * Obtain the library table to which you want to add the library. Use one of the following, depending on the library level: * `LibraryTablesRegistrar.getInstance().getLibraryTable()` @@ -74,19 +72,19 @@ To create a library, perform the following steps: * Create the library by calling `LibraryTable.createLibrary()` * Add contents to the library (see below) * For a module-level library, commit the modifiable model returned by `ModuleRootManager.getInstance(module).getModifiableModel()`. - -For module-level libraries, you can also use simplified APIs in the [`ModuleRootModificationUtil`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ModuleRootModificationUtil.java) class to add a library with a single API call. + +For module-level libraries, you can also use simplified APIs in the [`ModuleRootModificationUtil`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ModuleRootModificationUtil.java) class to add a library with a single API call. You can find an example of using these APIs in the [project_model](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/project_model/src/main/java/org/intellij/sdk/project/model/ModificationAction.java) code sample. ### Adding Contents or Modifying a Library -To add or change the roots of a library, you need to perform the following steps: +To add or change the roots of a library, you need to perform the following steps: * Get a [write action](../../basics/architectural_overview/general_threading_rules.md#readwrite-lock) * Get a **modifiable model** for the library, using `Library.getModifiableModel()` * Use methods such as `Library.ModifiableModel.addRoot()` to perform the necessary changes * Commit the model using `Library.ModifiableModel.commit()`. - + ### Adding a Library Dependency to a Module -Use `ModuleRootModificationUtil.addDependency(module, library)` from under a write action. +Use `ModuleRootModificationUtil.addDependency(module, library)` from under a write action. ### Checking Belonging to a Library The [`ProjectFileIndex`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java) interface implements a number of methods you can use to check whether the specified file belongs to the project library classes or library sources. @@ -112,5 +110,6 @@ More details on libraries can be found in the [plugin_model](https://github.com/ ## Predefined Libraries EP: `com.intellij.additionalLibraryRootsProvider` -[`AdditionalLibraryRootsProvider`](upsource:///platform/projectModel-impl/src/com/intellij/openapi/roots/AdditionalLibraryRootsProvider.java) -Allows providing synthetic/predefined libraries ([`SyntheticLibrary`](upsource:///platform/projectModel-impl/src/com/intellij/openapi/roots/SyntheticLibrary.java)) in a project without exposing them in the model. By default, they're also hidden from UI. +[`AdditionalLibraryRootsProvider`](upsource:///platform/projectModel-impl/src/com/intellij/openapi/roots/AdditionalLibraryRootsProvider.java) +Allows providing synthetic/predefined libraries ([`SyntheticLibrary`](upsource:///platform/projectModel-impl/src/com/intellij/openapi/roots/SyntheticLibrary.java)) in a project without exposing them in the model. +By default, they're also hidden from UI. diff --git a/reference_guide/project_model/module.md b/reference_guide/project_model/module.md index c3e491a5b..95b41e02b 100644 --- a/reference_guide/project_model/module.md +++ b/reference_guide/project_model/module.md @@ -3,24 +3,24 @@ title: Module --- -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. +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. The key components of a module are: - * **Content roots** - the directories where the files belonging to the module (source code, resources, etc.) - are stored. Each directory can belong to one and only one module; it's not possible to share a content root - between multiple modules. - * **Source roots** - A content root can have multiple **source roots** underneath it. Source roots can have different types: - regular source roots, test source roots, resource roots, etc. In IntelliJ IDEA, source roots are used as roots of the package hierarchy - structure (Java classes directly under a source root will be in the root package). Source roots can also be used to - implement more fine-grained dependency checks (code under a regular source root cannot depend on code under a test - source root). - > **NOTE** Not all other IntelliJ Platform-based IDEs use source roots. - * **Order entries** - the dependencies of a module, which are stored in an ordered list. A dependency can be a reference - to an [SDK](sdk.md), a [library](library.md), or another module. - * **[Facets](facet.md)** - the list of framework-specific configuration entries. +* **Content roots** - the directories where the files belonging to the module (source code, resources, etc.) are stored. + Each directory can belong to one and only one module; it's not possible to share a content root between multiple modules. +* **Source roots** - A content root can have multiple **source roots** underneath it. + Source roots can have different types: regular source roots, test source roots, resource roots, etc. + In IntelliJ IDEA, source roots are used as roots of the package hierarchy structure. + Java classes directly under a source root will be in the root package. + Source roots can also be used to implement more fine-grained dependency checks. + Code under a regular source root cannot depend on code under a test source root. + > **NOTE** Not all other IntelliJ Platform-based IDEs use source roots. +* **Order entries** - the dependencies of a module, which are stored in an ordered list. + A dependency can be a reference to an [SDK](sdk.md), a [library](library.md), or another module. +* **[Facets](facet.md)** - the list of framework-specific configuration entries. -In addition to that, a module can store other settings, such as a module-specific [SDK](sdk.md), compile output path -settings, etc. +In addition to that, a module can store other settings, such as a module-specific [SDK](sdk.md), compile output path settings, etc. Plugins can store additional data associated with a module by creating facets or module-level components. @@ -42,7 +42,8 @@ Use the `ModuleManager.getModules()` method. ### How do I get dependencies and classpath of a module? -_Order entries_ include SDK, libraries and other modules the module uses. With the *IntelliJ IDEA* UI, you can view order entries for a module on the [Dependencies](https://www.jetbrains.com/help/idea/dependencies-tab.html) tab of the *Project Structure* dialog box. +_Order entries_ include SDK, libraries and other modules the module uses. +With the *IntelliJ IDEA* UI, you can view order entries for a module on the [Dependencies](https://www.jetbrains.com/help/idea/dependencies-tab.html) tab of the *Project Structure* dialog box. To explore the [module dependencies](https://www.jetbrains.com/help/idea/dependencies-tab.html), use the [`OrderEnumerator`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/OrderEnumerator.java) class. @@ -54,7 +55,8 @@ VirtualFile[] roots = ModuleRootManager.getInstance(module).orderEntries().class ### How do I get the SDK the module uses? -Use the `ModuleRootManager.getSdk()` method. This method returns a value of the [`Sdk`](upsource:///platform/projectModel-api/src/com/intellij/openapi/projectRoots/Sdk.java) type. +Use the `ModuleRootManager.getSdk()` method. +This method returns a value of the [`Sdk`](upsource:///platform/projectModel-api/src/com/intellij/openapi/projectRoots/Sdk.java) type. The following code snippet illustrates how you can get detailed information on SDK the specified module uses: @@ -67,7 +69,8 @@ String jdkInfo = "Module: " + module.getName() + " SDK: " + SDK.getName() + " SD ### How do I get a list of modules on which this module directly depends? -Use the `ModuleRootManager.getDependencies()` method to get an array of the `Module` type values or the `ModuleRootManager.getDependencyModuleNames()` to get an array of module names. To clarify, consider the following code snippet: +Use the `ModuleRootManager.getDependencies()` method to get an array of the `Module` type values or the `ModuleRootManager.getDependencyModuleNames()` to get an array of module names. +To clarify, consider the following code snippet: ```java ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); @@ -112,7 +115,8 @@ VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoo ### Checking Belonging to a Module Source Root -To check if a virtual file or directory belongs to a module source root, use the `ProjectFileIndex.getSourceRootForFile()` method. This method returns `null` if the file or directory does not belong to any source root of modules in the project. +To check if a virtual file or directory belongs to a module source root, use the `ProjectFileIndex.getSourceRootForFile()` method. +This method returns `null` if the file or directory does not belong to any source root of modules in the project. ```java VirtualFile moduleSourceRoot = ProjectRootManager.getInstance(project).getFileIndex().getSourceRootForFile(virtualFileOrDirectory); @@ -120,8 +124,7 @@ VirtualFile moduleSourceRoot = ProjectRootManager.getInstance(project).getFileIn ## Receiving Notifications About Module Changes -To receive notifications about module changes (modules being added, removed or renamed), -use the [message bus](/reference_guide/messaging_infrastructure.md) and the `ProjectTopics.MODULES` topic: +To receive notifications about module changes (modules being added, removed or renamed), use the [message bus](/reference_guide/messaging_infrastructure.md) and the `ProjectTopics.MODULES` topic: ```java project.getMessageBus().connect().subscribe(ProjectTopics.MODULES, new ModuleListener() { @@ -131,4 +134,3 @@ project.getMessageBus().connect().subscribe(ProjectTopics.MODULES, new ModuleLis } }); ``` - diff --git a/reference_guide/project_model/project.md b/reference_guide/project_model/project.md index 13dab06fe..43724dc30 100644 --- a/reference_guide/project_model/project.md +++ b/reference_guide/project_model/project.md @@ -3,25 +3,25 @@ title: Project --- -In the *IntelliJ Platform*, a project encapsulates all the source code, libraries, and build instructions into a single organizational unit. -Everything done in the IDE is accomplished within the context of a project. -A project defines some collections referred to as modules and libraries. +In the *IntelliJ Platform*, a project encapsulates all the source code, libraries, and build instructions into a single organizational unit. +Everything done in the IDE is accomplished within the context of a project. +A project defines some collections referred to as modules and libraries. Depending on the logical and functional requirements for the project, a single-module or a multi-module project is possible. ## Working with Projects -The *IntelliJ Platform* stores the project configuration data in XML files. +The *IntelliJ Platform* stores the project configuration data in XML files. The list of those files depends on the chosen [project](https://www.jetbrains.com/help/idea/about-projects.html) format. -For file-based format projects (legacy), the information core to the project itself (e.g., location of the component modules, compiler settings, etc.) is stored in the `%project_name%.ipr` file. -The information about modules the project includes is stored in `%module_name%.iml` files. +For file-based format projects (legacy), the information core to the project itself (e.g., location of the component modules, compiler settings, etc.) is stored in the `%project_name%.ipr` file. +The information about modules the project includes is stored in `%module_name%.iml` files. Module files are created for each module. -For directory-based format projects, the project and workspace settings are stored in a number of XML files under the `%project_home_directory%/.idea` directory. -Each XML file is responsible for its own set of settings and can be recognized by its name: `projectCodeStyle.xml`, `encodings.xml`, `vcs.xml` etc. +For directory-based format projects, the project and workspace settings are stored in a number of XML files under the `%project_home_directory%/.idea` directory. +Each XML file is responsible for its own set of settings and can be recognized by its name: `projectCodeStyle.xml`, `encodings.xml`, `vcs.xml` etc. As for the file-based format projects, `.iml` files describe modules. -Note that direct access to project files isn't required to load or save settings. +Note that direct access to project files isn't required to load or save settings. See [Persisting State of Components](../../basics/persisting_state_of_components.md) for more information. To work with projects and project files, use the following classes and interfaces: @@ -30,11 +30,12 @@ To work with projects and project files, use the following classes and interface * [`ProjectManager`](upsource:///platform/projectModel-api/src/com/intellij/openapi/project/ProjectManager.java) * [`ProjectFileIndex`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java) -Other classes for working with the project model are located in the [`projectModel-api.openapi`](upsource:///platform/projectModel-api/src/com/intellij/openapi) package. +Other classes for working with the project model are located in the [`projectModel-api.openapi`](upsource:///platform/projectModel-api/src/com/intellij/openapi) package. Basic API classes and interfaces for the concepts of [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java), [`Module`](upsource:///platform/core-api/src/com/intellij/openapi/module/Module.java) and [`Application`](upsource:///platform/core-api/src/com/intellij/openapi/application/Application.java) are placed in the [`core-api.openapi`](upsource:///platform/core-api/src/com/intellij/openapi) package. ### Getting a List of Source Roots for All Modules in a Project -Use the `ProjectRootManager.getContentSourceRoots()` method. To clarify this, consider the following code snippet: +Use the `ProjectRootManager.getContentSourceRoots()` method. +To clarify this, consider the following code snippet: ```java String projectName = project.getName(); @@ -51,7 +52,7 @@ ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getF ``` ### Getting the Content or Source Root to Which the a File or Directory Belongs -Use the `ProjectFileIndex.getContentRootForFile()` and `ProjectFileIndex.getSourceRootForFile()` methods. +Use the `ProjectFileIndex.getContentRootForFile()` and `ProjectFileIndex.getSourceRootForFile()` methods. For example: ```java @@ -60,7 +61,7 @@ VirtualFile moduleSourceRoot = ProjectRootManager.getInstance(project).getFileIn ``` Note that this method returns `null` if the file or directory does not belong to any source root of modules in the project. - + ### Checking Whether a File or Directory Is Related to the Project Libraries The [`ProjectFileIndex`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java) interface implements a number of methods you can use to check whether the specified file belongs to the project library classes or library sources: * `isLibraryClassFile()`: Returns `true` if the specified `virtualFile` is a compiled class file. @@ -68,13 +69,14 @@ The [`ProjectFileIndex`](upsource:///platform/projectModel-api/src/com/intellij/ * `isInLibrarySource()`: Returns `true` if the specified `virtualFileOrDirectory` belongs to library sources. ### Getting the Project SDK -Note that by default, the project modules use the project SDK. -Optionally, you can configure an individual SDK for each module. +Note that by default, the project modules use the project SDK. +Optionally, you can configure an individual SDK for each module. See [SDK](sdk.md) for more details. ## Changing the Project Structure -Utility classes used for modifying the project structure can be found in the package [`projectModel-impl.openapi`](upsource:///platform/projectModel-impl/src/com/intellij/openapi). Its [`roots`](upsource:///platform/projectModel-impl/src/com/intellij/openapi/roots/) subpackage contains instances and utilities intended for work with project and module source roots, including [`ModuleRootModificationUtil`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ModuleRootModificationUtil.java) and [`ProjectRootUtil`](upsource:///platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/ProjectRootUtil.java). Project structure -changes need to be performed in a [write action](/basics/architectural_overview/general_threading_rules.md#readwrite-lock). +Utility classes used for modifying the project structure can be found in the package [`projectModel-impl.openapi`](upsource:///platform/projectModel-impl/src/com/intellij/openapi). +Its [`roots`](upsource:///platform/projectModel-impl/src/com/intellij/openapi/roots/) subpackage contains instances and utilities intended for work with project and module source roots, including [`ModuleRootModificationUtil`](upsource:///platform/projectModel-api/src/com/intellij/openapi/roots/ModuleRootModificationUtil.java) and [`ProjectRootUtil`](upsource:///platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/ProjectRootUtil.java). +Project structure changes need to be performed in a [write action](/basics/architectural_overview/general_threading_rules.md#readwrite-lock). Refer to the [project_model](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/project_model/src/main/java/org/intellij/sdk/project/model/ModificationAction.java) code sample to learn how project structure modification can be implemented. diff --git a/reference_guide/project_model/sdk.md b/reference_guide/project_model/sdk.md index 635644adc..feb727644 100644 --- a/reference_guide/project_model/sdk.md +++ b/reference_guide/project_model/sdk.md @@ -3,11 +3,11 @@ title: SDK --- -Every project uses a Software Development Kit (SDK). -For Java projects, the SDK is referred to as the JDK (Java Development Kit). -The SDK determines which API library is used to build the project. -If a project is multi-module, the project SDK by default is common for all modules within the project. -Optionally, individual SDKs for each module can be configured. +Every project uses a Software Development Kit (SDK). +For Java projects, the SDK is referred to as the JDK (Java Development Kit). +The SDK determines which API library is used to build the project. +If a project is multi-module, the project SDK by default is common for all modules within the project. +Optionally, individual SDKs for each module can be configured. For more information about SDKs, see [SDK](https://www.jetbrains.com/help/idea/working-with-sdks.html) in the IntelliJ IDEA Web Help. ## Getting Project SDK Information @@ -26,23 +26,23 @@ Sdk projectSdk = ProjectRootManager.getInstance(project).getProjectSdk(); ``` * To get the project level SDK name: - - ```java + + ```java String projectSDKName = ProjectRootManager.getInstance(project).getProjectSdkName(); ``` * To set the project level SDK: - + ```java ProjectRootManager.getInstance(project).setProjectSdk(Sdk jdk); ``` * To set the project level SDK name: - + ```java ProjectRootManager.getInstance(project).setProjectSdkName(String name); ``` - + See the [project_model](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/project_model/src/main/java/org/intellij/sdk/project/model/ProjectSdkAction.java) code sample to get more familiar with SDK manipulation toolset. ## Available SDKs @@ -67,9 +67,9 @@ public boolean setupSdkPaths(@NotNull Sdk sdk, @NotNull SdkModel sdkModel) { To let a user select an SDK, see [`ProjectJdksEditor`](upsource:///java/idea-ui/src/com/intellij/openapi/projectRoots/ui/ProjectJdksEditor.java). -However, it is not recommended to use "SDK" in non-IntelliJ IDEA IDEs. Although "SDK" is available in most JetBrains products, `ProjectJdksEditor` is specific to Java, making the operation around "SDK" difficult. -The recommended way of managing "SDK" settings is to create a [`CustomStepProjectGenerator`](upsource:///platform/lang-impl/src/com/intellij/ide/util/projectWizard/CustomStepProjectGenerator.java) -implementation and save settings in a [`PersistentStateComponent`](/basics/persisting_state_of_components.md). +However, it is not recommended to use "SDK" in non-IntelliJ IDEA IDEs. +Although "SDK" is available in most JetBrains products, `ProjectJdksEditor` is specific to Java, making the operation around "SDK" difficult. +The recommended way of managing "SDK" settings is to create a [`CustomStepProjectGenerator`](upsource:///platform/lang-impl/src/com/intellij/ide/util/projectWizard/CustomStepProjectGenerator.java) implementation and save settings in a [`PersistentStateComponent`](/basics/persisting_state_of_components.md). ## Assisting in Setting Up an SDK Register the implementation of [`ProjectSdkSetupValidator`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/daemon/ProjectSdkSetupValidator.java) in extension point `com.intellij.projectSdkSetupValidator` to provide quick fix. diff --git a/reference_guide/project_wizard.md b/reference_guide/project_wizard.md index 80886a430..2cdc41820 100644 --- a/reference_guide/project_wizard.md +++ b/reference_guide/project_wizard.md @@ -5,20 +5,17 @@ title: Project Wizard. Adding Support for Creating New Project Types. ## Project Wizard -Working with the project wizard can be illustrated with the -[RedLine SmallTalk plugin](https://github.com/bulenkov/RedlineSmalltalk) +Working with the project wizard can be illustrated with the [RedLine SmallTalk plugin](https://github.com/bulenkov/RedlineSmalltalk) ## Implementing New Module Type Additional support for specific tools and technologies is usually done via implementing some certain module type which is attached to the project. -New module type should be derived from the class -[`ModuleType`](upsource:///platform/lang-api/src/com/intellij/openapi/module/ModuleType.java). +New module type should be derived from the class [`ModuleType`](upsource:///platform/lang-api/src/com/intellij/openapi/module/ModuleType.java). ## Project Wizard -Main utilities to configure a custom project wizard can be found in the package -[`lang-api.ide.util.projectWizard`](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard). +Main utilities to configure a custom project wizard can be found in the package [`lang-api.ide.util.projectWizard`](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard). These classes and interfaces serve the following purposes: * Modification of the configuration wizard view @@ -35,21 +32,13 @@ To create a new module type and an extension ``` -to the -[`plugin.xml`](https://github.com/bulenkov/RedlineSmalltalk/blob/master/resources/META-INF/plugin.xml). -A custom module type should extend the -[`ModuleType`](upsource:///platform/lang-api/src/com/intellij/openapi/module/ModuleType.java) -generic from -[`ModuleBuilder`](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java). -The following -[module type implementation](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleType.java) -of a custom module type show how this instance can be registered and implemented. +to the [`plugin.xml`](https://github.com/bulenkov/RedlineSmalltalk/blob/master/resources/META-INF/plugin.xml). +A custom module type should extend the [`ModuleType`](upsource:///platform/lang-api/src/com/intellij/openapi/module/ModuleType.java) generic from [`ModuleBuilder`](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java). +The following [module type implementation](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleType.java) of a custom module type show how this instance can be registered and implemented. ### Implementing Module Builder -To set up a new module environment -[`ModuleBuilder`](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java) -class should be extended and registered as an extension point like the following snippet shows: +To set up a new module environment [`ModuleBuilder`](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java) class should be extended and registered as an extension point like the following snippet shows: ```xml @@ -59,49 +48,33 @@ class should be extended and registered as an extension point like the following Functionality which is mandatory to implement consists of: -* Setting up a root model for the new module by overriding +* Setting up a root model for the new module by overriding + ```java + public abstract void setupRootModel(ModifiableRootModel modifiableRootModel) throws ConfigurationException; + ``` +* Getting a module type + ```java + public abstract ModuleType getModuleType(); + ``` - ```java - public abstract void setupRootModel(ModifiableRootModel modifiableRootModel) throws ConfigurationException; - ``` +See [`JavaModuleBuilder`](upsource:///java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java) to understand better how to implement a module builder. -* Getting a module type - - ```java - public abstract ModuleType getModuleType(); - ``` - -See -[`JavaModuleBuilder`](upsource:///java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java) -to understand better how to implement a module builder. - -If your module type is based on the java module and meant to support Java as well, extending -[`JavaModuleBuilder`](upsource:///java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java) -is enough. +If your module type is based on the java module and meant to support Java as well, extending [`JavaModuleBuilder`](upsource:///java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java) is enough. No extension point needs to be registered. -Refer to -[SmallTalk module type](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleType.java) -to see how -[`JavaModuleBuilder`](upsource:///java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java) -can be derived. +Refer to [SmallTalk module type](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleType.java) to see how [`JavaModuleBuilder`](upsource:///java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java) can be derived. ### Implementing Module Builder Listener -Module builder listener reacts on a new module creation, which could be done either as a part of the project creation process, -or as adding a new module to the already existing project. -To provide a certain behavior right after a module has been created, module builder should implement -[`ModuleBuilderListener`](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilderListener.java) +Module builder listener reacts on a new module creation, which could be done either as a part of the project creation process, or as adding a new module to the already existing project. +To provide a certain behavior right after a module has been created, module builder should implement [`ModuleBuilderListener`](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilderListener.java) Method ```java public void moduleCreated(@NotNull final Module module); ``` -executed tasks right after a module has been created, -these may include configuring roots looking up for an SDK and setting it up, adding a specific facet if required and others. -For more details please see the following -[SmallTalk custom module type](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleType.java) -implementation. +executed tasks right after a module has been created, these may include configuring roots looking up for an SDK and setting it up, adding a specific facet if required and others. +For more details please see the following [SmallTalk custom module type](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleType.java) implementation. ### Adding New Wizard Steps @@ -111,33 +84,24 @@ Adding new steps to the module wizard can be done by overriding the public ModuleWizardStep[] createWizardSteps(WizardContext wizardContext, ModulesProvider modulesProvider); ``` -method in a custom -[module builder](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleBuilder.java). +method in a custom [module builder](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleBuilder.java). If this method returns a non-empty array of ModuleWizardStep objects, new steps will be shown in their indexing order while creating a new module. -The following -[implementation](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleWizardStep.java) -for the SmallTalk project type illustrates how a custom wizard step can be created. -The -[`RsModuleWizardStep`](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleWizardStep.java) -class is derived from -[`ModuleWizardStep`](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleWizardStep.java), -which has two methods to be overridden: +The following [implementation](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleWizardStep.java) for the SmallTalk project type illustrates how a custom wizard step can be created. +The [`RsModuleWizardStep`](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsModuleWizardStep.java) class is derived from [`ModuleWizardStep`](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleWizardStep.java), which has two methods to be overridden: -* ```java - public JComponent getComponent(); - ``` - defines how the step will look like -* ```java - public void updateDataModel(); - ``` - commits data from UI into ModuleBuilder and WizardContext +* ```java + public JComponent getComponent(); + ``` + defines how the step will look like +* ```java + public void updateDataModel(); + ``` + commits data from UI into ModuleBuilder and WizardContext ## Facet Facets in IntelliJ are the way to store multiple kinds of module-specific settings, for instance to make a language support or framework available in some given module. -To understand facets better from the point of view of an end-user, please see -[Facet](/reference_guide/project_model/facet.md) -documentation section. +To understand facets better from the point of view of an end-user, please see the [Facet](/reference_guide/project_model/facet.md) documentation section. ## Implementing Project Structure Detector @@ -153,7 +117,8 @@ public abstract DirectoryProcessingResult detectRoots(@NotNull File dir, @NotNul Refer to the [Smalltalk project structure detector](https://github.com/bulenkov/RedlineSmalltalk/blob/master/src/st/redline/smalltalk/module/RsProjectStructureDetector.java) -But detecting the files is not enough, you also need to create a module for the project if appropriate by implementing `setupProjectStructure()`. Here is an example that creates a module if no other modules exist in the project structure. +But detecting the files is not enough, you also need to create a module for the project if appropriate by implementing `setupProjectStructure()`. +Here is an example that creates a module if no other modules exist in the project structure. ```java @Override diff --git a/reference_guide/settings_groups.md b/reference_guide/settings_groups.md index 061ba8025..93e7cb855 100644 --- a/reference_guide/settings_groups.md +++ b/reference_guide/settings_groups.md @@ -7,23 +7,23 @@ title: Custom Settings Groups As described in [Extension Points for Settings](settings_guide.md#extension-points-for-settings), custom _Settings_ can be declared as children of existing parent groups such as `tools`. These parent groups are the existing categories of Settings in the IntelliJ Platform-based IDE. -However, suppose the custom Settings are rich enough to require multiple levels? +However, suppose the custom Settings are rich enough to require multiple levels? For example, a custom Setting implementation has multiple sub-Settings implementations. Extension Point declarations can create this kind of multilayer Settings hierarchy. - + * bullet list {:toc} ## Extension Points for Parent-Child Settings Relationships -There are multiple ways of creating parent-child relationships in groups of Settings: in implementations, or Extension Point declarations. -However, there are performance penalties for creating these relationships in implementations because the objects must be instantiated to determine the relationships. -This section describes the syntax for declaring more complex parent-child relationships in `com.intellij.projectConfigurable` or `com.intellij.applicationConfigurable` EPs. +There are multiple ways of creating parent-child relationships in groups of Settings: in implementations, or Extension Point declarations. +However, there are performance penalties for creating these relationships in implementations because the objects must be instantiated to determine the relationships. +This section describes the syntax for declaring more complex parent-child relationships in `com.intellij.projectConfigurable` or `com.intellij.applicationConfigurable` EPs. -> **NOTE** An application configurable can be a parent of a project configurable. +> **NOTE** An application configurable can be a parent of a project configurable. -There are two ways of declaring parent-child relationships using the `com.intellij.projectConfigurable` or `com.intellij.applicationConfigurable` EPs. -The first is to use separate EP declarations that are tied together by the value of one attribute. -The second method is to use nested declarations. +There are two ways of declaring parent-child relationships using the `com.intellij.projectConfigurable` or `com.intellij.applicationConfigurable` EPs. +The first is to use separate EP declarations that are tied together by the value of one attribute. +The second method is to use nested declarations. ### Parent-Child Settings Using Separate EPs One way of declaring a parent-child relationship is by using two separate declarations. @@ -33,14 +33,14 @@ If the `id` attribute of the parent is known, a plugin can add Settings as a chi For example, below are two declarations for project Settings. The first gets added to the `tools` group, and the second gets added to the `id` of the parent. The `id` of the second, child `` adds a suffix (`servers`) to the `id` of the parent. - + ```xml - - - @@ -50,12 +50,12 @@ See the [Attributes for Parent-Child Settings EPs](#attributes-for-parent-child- ### Parent-Child Settings Using Nested EPs A shorthand for the separate declaration approach is using the `com.intellij.configurable` EP. -This approach nests the child's Settings declaration within the `com.intellij.projectConfigurable` or `com.intellij.applicationConfigurable` EP. +This approach nests the child's Settings declaration within the `com.intellij.projectConfigurable` or `com.intellij.applicationConfigurable` EP. Using `` EP would not be possible if the parent Settings were declared in another plugin or file. -In that case, [Parent-Child Settings Using Separate EPs](#parent-child-settings-using-separate-eps) would be used. +In that case, [Parent-Child Settings Using Separate EPs](#parent-child-settings-using-separate-eps) would be used. -When using `` EP there isn't a `parentId` for the child because the nesting implies it. -As with using separate EP declarations, formatting restrictions are placed on the child's `id` attribute - the suffix (`servers`) gets added. +When using `` EP there isn't a `parentId` for the child because the nesting implies it. +As with using separate EP declarations, formatting restrictions are placed on the child's `id` attribute - the suffix (`servers`) gets added. See the [Attributes for Parent-Child Settings EPs](#attributes-for-parent-child-settings-eps) section. The example below demonstrates a `` EP declaration: @@ -70,7 +70,7 @@ The example below demonstrates a `` EP declaration: ``` -Within the parent `` EP declaration above, more `` declarations could be added as sibling Settings. +Within the parent `` EP declaration above, more `` declarations could be added as sibling Settings. ### Attributes for Parent-Child Settings EPs There is only one unique attribute when declaring a child Settings EP. @@ -82,13 +82,14 @@ For the child of a parent, the `id` attribute becomes compound: |:--- | :---: |:--- | | `id` | Y | Compound FQN of implementation based on `com.intellij.openapi.options.Configurable` in the form: `XX.YY` where:
`XX` is the parent Settings component FQN-based id.
`YY` is unique to the child among other siblings. | -> **TIP** All children share the parent's `id` as the basis of their own `id`. All children have an `id` suffix that is unique among their siblings. +> **TIP** All children share the parent's `id` as the basis of their own `id`. +> All children have an `id` suffix that is unique among their siblings. ## Implementations for Parent-Child Settings -Implementations can be based on [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java), [`ConfigurableProvider`](upsource:///platform/platform-api/src/com/intellij/openapi/options/ConfigurableProvider.java) or one of their subtypes. -For more information about creating Settings implementations, see [Implementations for Settings Extension Points](settings_guide.md#implementations-for-settings-extension-points). +Implementations can be based on [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java), [`ConfigurableProvider`](upsource:///platform/platform-api/src/com/intellij/openapi/options/ConfigurableProvider.java) or one of their subtypes. +For more information about creating Settings implementations, see [Implementations for Settings Extension Points](settings_guide.md#implementations-for-settings-extension-points). ### Configurable Marker Interfaces The `Configurable.Composite` interface indicates a configurable component has child components. The preferred approach is to specify child components in the [EP declaration](#extension-points-for-parent-child-settings-relationships). -Using the `Composite` interface incurs the penalty of loading child classes while building the tree of Settings Swing components. +Using the `Composite` interface incurs the penalty of loading child classes while building the tree of Settings Swing components. diff --git a/reference_guide/settings_guide.md b/reference_guide/settings_guide.md index 1c482f7d9..4358e7ffc 100644 --- a/reference_guide/settings_guide.md +++ b/reference_guide/settings_guide.md @@ -11,7 +11,7 @@ Plugins can create and store Settings to capture their configuration in a way th The User Interface (UI) for these custom Settings can be added to the [IDE Settings dialog](https://www.jetbrains.com/help/idea/settings-preferences-dialog.html). Settings can [affect different levels](https://www.jetbrains.com/help/idea/configuring-project-and-ide-settings.html) of scope. -This document describes adding custom Settings at the Project and Application (or Global, IDE) levels. +This document describes adding custom Settings at the Project and Application (or Global, IDE) levels. * bullet list {:toc} @@ -20,10 +20,11 @@ This document describes adding custom Settings at the Project and Application (o Custom Settings implementations are declared in a plugin's configuration (`plugin.xml`) file using one of two Extension Points (EPs), depending on the level of the Settings. Many [attributes](#settings-declaration-attributes) are shared between the EP declarations. -Application and Project Settings typically provide an implementation based on the [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java) interface because they do not have runtime dependencies. +Application and Project Settings typically provide an implementation based on the [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java) interface because they do not have runtime dependencies. See [Implementations for Settings Extension Points](#implementations-for-settings-extension-points) for more information. - -> **NOTE** For performance reasons, the recommended approach is to declare as much information as possible about a Settings' implementation using attributes in the Extension Point. If it is not declared, the component must be loaded to retrieve it from the implementation, degrading UI responsiveness. + +> **NOTE** For performance reasons, the recommended approach is to declare as much information as possible about a Settings' implementation using attributes in the Extension Point. +> If it is not declared, the component must be loaded to retrieve it from the implementation, degrading UI responsiveness. ### Declaring Application Settings Settings at the Application level use the `com.intellij.applicationConfigurable` EP. @@ -36,7 +37,7 @@ See [Settings Declaration Attributes](#settings-declaration-attributes) for more
-``` +``` ### Declaring Project Settings Project level Settings use the `com.intellij.projectConfigurable` EP. @@ -50,9 +51,9 @@ See [Settings Declaration Attributes](#settings-declaration-attributes) for deta id="org.company.ProjectSettingsConfigurable" displayName="My Project Settings" nonDefaultProject="true"/>
-``` +``` -### Settings Declaration Attributes +### Settings Declaration Attributes Readers are encouraged to review the Javadoc comments for [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java) because the attribute information applies to `ConfigurableProvider` as well as `Configurable`, as noted. This section provides some additional clarification of those comments. @@ -72,13 +73,13 @@ The attributes supported by `com.intellij.applicationConfigurable` and `com.inte | `dynamic` | `Configurable.Composite` | N | This component's children are dynamically calculated by calling the `getConfigurables()` method.
Not recommended because it requires loading additional classes while building a Settings tree. If possible, use XML attributes instead. | | `childrenEPName` | `Configurable` | N | Specifies the FQN name of the Extension Point that will be used to calculate the children of this component. | -**Attribute Notes:** -1) Either `instance` or `provider` must be specified depending on the implementation. -2) One of these attribute sets must be specified depending on whether the displayed Settings name is localized. +**Attribute Notes:** +1) Either `instance` or `provider` must be specified depending on the implementation. +2) One of these attribute sets must be specified depending on whether the displayed Settings name is localized. 3) If both `groupId` and `parentId` are specified, a warning is logged. Also, see _default_ entry in [Values for Parent ID Attribute](#values-for-parent-id-attribute). #### Values for Parent ID Attribute -The table below shows the allowed values for the `parentId` attribute. +The table below shows the allowed values for the `parentId` attribute. See the [previous section](#table-of-attributes) for all supported attributes. | `parentId` Value | Group | Details | @@ -96,29 +97,29 @@ See the [previous section](#table-of-attributes) for all supported attributes. ## Implementations for Settings Extension Points -Implementations for `com.intellij.projectConfigurable` and `com.intellij.applicationConfigurable` EPs can have one of two bases: +Implementations for `com.intellij.projectConfigurable` and `com.intellij.applicationConfigurable` EPs can have one of two bases: * The [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java) interface, which provides a named configurable component with a Swing form. Most Settings providers are based on the `Configurable` interface or one of its sub- or supertypes. * The [`ConfigurableProvider`](upsource:///platform/platform-api/src/com/intellij/openapi/options/ConfigurableProvider.java) class, which can hide a configurable component from the Settings dialog based on runtime conditions. ### The Configurable Interface -Many Settings in the `intellij-community` code base implement `Configurable` or one of its subtypes, such as [`SearchableConfigurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/SearchableConfigurable.java). +Many Settings in the `intellij-community` code base implement `Configurable` or one of its subtypes, such as [`SearchableConfigurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/SearchableConfigurable.java). Readers are encouraged to review the Javadoc comments for `Configurable`. #### Constructors -Implementations must meet several requirements for constructors. -* Application Settings implementations, declared using the [`applicationConfiguration` EP](#declaring-application-settings), must have a default constructor with no arguments. +Implementations must meet several requirements for constructors. +* Application Settings implementations, declared using the [`applicationConfiguration` EP](#declaring-application-settings), must have a default constructor with no arguments. * Project Settings implementations, declared using the [`projectSettings` EP](#declaring-project-settings), must declare a constructor with a single argument of type [`Project`](upsource:///platform/core-api/src/com/intellij/openapi/project/Project.java). * Beginning in 2020.2, constructor injection (other than for `Project`) is not allowed. For a `Configurable` implementation correctly declared using an EP, the implementation's constructor is not invoked by the IntelliJ Platform until a user chooses the corresponding Settings `displayName` in the Settings Dialog menu. -> **WARNING** The IntelliJ Platform may instantiate a `Configurable` implementation on a background thread, so creating Swing components in a constructor can degrade UI responsiveness. +> **WARNING** The IntelliJ Platform may instantiate a `Configurable` implementation on a background thread, so creating Swing components in a constructor can degrade UI responsiveness. #### IntelliJ Platform Interactions with Configurable The instantiation of a generic `Configurable` implementation is documented in the interface file. A few high-level points are reviewed here: -* The `Configurable.reset()` method is invoked immediately after `Configurable.createComponent()`. +* The `Configurable.reset()` method is invoked immediately after `Configurable.createComponent()`. Initialization of Setting values in the constructor or `createComponent()` is unnecessary. * See the [Constructors](#constructors) section for information about when a Settings object is instantiated. * Once instantiated, a `Configurable` instance's lifetime continues regardless of whether the implementation's Settings are changed, or the user chooses a different entry on the Settings Dialog menu. @@ -129,11 +130,11 @@ To open Settings dialog or show specific `Configurable`, see [`ShowSettingsUtil` #### Configurable Marker Interfaces Implementations based on `Configurable` can implement marker interfaces, which provide additional flexibility in the implementation. - + The following nested interfaces are markers, which convey information about the form to the IntelliJ Platform: * `Configurable.NoScroll` - Notifies the Settings dialog not to add scroll bars to the form. By default, a plugin's Settings component is put into a scrollable pane. - However, a Settings panel can have a `JTree`, which requires its own `JScrollPane`. + However, a Settings panel can have a `JTree`, which requires its own `JScrollPane`. So `NoScroll` interface should be used to remove the outer `JScrollPane`. * `Configurable.NoMargin` - Notifies the Settings dialog not to add an empty border to the form. By default, an empty border is added for a plugin's Settings component. @@ -144,7 +145,7 @@ These subtypes are based on `com.intellij.openapi.options.ConfigurableEP`. For example, **Settings/Preferences \| Editor \| General \|Appearance** allows adding Settings via [`EditorSmartKeysConfigurableEP`](upsource:///platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurableEP.java) and `com.intellij.editorSmartKeysConfigurable` EP. ### The ConfigurableProvider Class -The [`ConfigurableProvider`](upsource:///platform/platform-api/src/com/intellij/openapi/options/ConfigurableProvider.java) class only provides a `Configurable` implementation if its runtime conditions are met. +The [`ConfigurableProvider`](upsource:///platform/platform-api/src/com/intellij/openapi/options/ConfigurableProvider.java) class only provides a `Configurable` implementation if its runtime conditions are met. The IntelliJ Platform first calls the `ConfigurableProvider.canCreateConfigurable()`, which evaluates runtime conditions to determine if Settings changes make sense in the current context. If the Settings make sense to display, `canCreateConfigurable()` returns `true`. In that case the IntelliJ Platform calls `ConfigurableProvider.createConfigurable()`, which returns the `Configurable` object for its Settings implementation. diff --git a/reference_guide/tomcat_integration.md b/reference_guide/tomcat_integration.md index a52ae3089..bf84d048c 100644 --- a/reference_guide/tomcat_integration.md +++ b/reference_guide/tomcat_integration.md @@ -5,4 +5,3 @@ title: Tomcat Integration The source code of the Tomcat plugin included in IntelliJ IDEA Ultimate is available as a sample for implementing application server integration plugins. You can find the code under *lib\src\src_tomcat.zip* in the main IntelliJ IDEA Ultimate distribution. - diff --git a/reference_guide/ui_themes/themes.md b/reference_guide/ui_themes/themes.md index 518fbea55..0859c1152 100644 --- a/reference_guide/ui_themes/themes.md +++ b/reference_guide/ui_themes/themes.md @@ -3,7 +3,7 @@ title: Creating Custom UI Themes --- -Creating a custom UI Theme is a process of choosing a base IDE Theme (_Light_ or _Darcula_,) then changing aspects of the base Theme definition. +Creating a custom UI Theme is a process of choosing a base IDE Theme (_Light_ or _Darcula_,) then changing aspects of the base Theme definition. Custom UI Themes can: * substitute icons, * change the colors of icons and UI controls, @@ -12,17 +12,17 @@ Custom UI Themes can: * add background images. ## The Structure of a UI Theme -UI Themes are components within IntelliJ Platform plugins. -Theme plugins should be stand-alone plugins, and not combined with other plugin functionality. +UI Themes are components within IntelliJ Platform plugins. +Theme plugins should be stand-alone plugins, and not combined with other plugin functionality. This approach is the best user experience because it avoids an IDE restart when installing a UI Theme plugin. UI Themes have several components: -* A required Theme description (JSON) file in the plugin project's `resources` folder. +* A required Theme description (JSON) file in the plugin project's `resources` folder. * A required `themeProvider` declaration in the plugin's `plugin.xml` file, located in the plugin project's `META-INF` folder. -* An optional Editor Scheme description (XML) file derived from an exported IDE editor scheme. +* An optional Editor Scheme description (XML) file derived from an exported IDE editor scheme. This file is located in the plugin project's `resources` folder. * An optional background image file, located in the plugin project's `resources` folder. -* Optional icon image files, located in the plugin project's `resources` folder. +* Optional icon image files, located in the plugin project's `resources` folder. ![UI Theme Components](img/theme_components.png) @@ -34,7 +34,7 @@ Creating a UI Theme follows this general sequence: * [Add an Editor Scheme or Background Image](themes_extras.md) to the plugin. * [Build and test](/basics/getting_started/running_and_debugging_a_plugin.md) the UI Theme plugin. * [Deploy the UI Theme plugin](/basics/getting_started/deploying_plugin.md) -* [Publish the UI Theme plugin](/basics/getting_started/publishing_plugin.md) +* [Publish the UI Theme plugin](/basics/getting_started/publishing_plugin.md) ## Creating Custom UI Themes @@ -42,11 +42,11 @@ Creating a UI Theme follows this general sequence: A UI Theme is added to an IntelliJ Platform plugin using the DevKit UI Theme Wizard. ### Creating a UI Theme with the DevKit Theme Wizard -The DevKit Wizard is part of the DevKit plugin, which is bundled with IntelliJ IDEA. +The DevKit Wizard is part of the DevKit plugin, which is bundled with IntelliJ IDEA. This Wizard can be used for both DevKit-based and Gradle-based plugins. While a plugin project is open in IntelliJ IDEA, select the `resources` folder in the _Project_ tool window. -From the main menu, select the _**New | Plugin DevKit | Theme**_ action. +From the main menu, select the _**New | Plugin DevKit | Theme**_ action. ![DevKit Wizard Action](img/devkit_wiz_action.png) @@ -56,15 +56,15 @@ The Wizard then prompts for the name of the new Theme, and the basis for the The ![DevKit Dialog](img/devkit_wiz_dialog.png) -The best practice is to name the new Theme the same as the name of the plugin. -The checkbox indicates the basis for the Theme. -Checking _Dark theme_ means basing the custom Theme on _Darcula_. -Leaving the box unchecked means basing the custom Theme on the default IntelliJ IDEA _Light_ Theme. +The best practice is to name the new Theme the same as the name of the plugin. +The checkbox indicates the basis for the Theme. +Checking _Dark theme_ means basing the custom Theme on _Darcula_. +Leaving the box unchecked means basing the custom Theme on the default IntelliJ IDEA _Light_ Theme. For the SDK code sample `theme_basics` the box is _unchecked_. -Clicking the _OK_ button creates a default Theme description file named `[themeName].theme.json` in the plugin project's `resources` folder. -In this example, the file is named `theme_basics.theme.json`. -The content of the default file is a short set of key–value pairs: +Clicking the _OK_ button creates a default Theme description file named `[themeName].theme.json` in the plugin project's `resources` folder. +In this example, the file is named `theme_basics.theme.json`. +The content of the default file is a short set of key–value pairs: ```json { @@ -77,13 +77,13 @@ The content of the default file is a short set of key–value pairs: } ``` -The `value` of the `name` key matches the first portion of the Theme description `[themeName].theme.json` file name. -The `value` of `name` is displayed in the [Theme](https://www.jetbrains.com/help/idea/settings-appearance.html) _Preferences_ dropdown when the UI Theme's plugin is installed in the IDE. +The `value` of the `name` key matches the first portion of the Theme description `[themeName].theme.json` file name. +The `value` of `name` is displayed in the [Theme](https://www.jetbrains.com/help/idea/settings-appearance.html) _Preferences_ dropdown when the UI Theme's plugin is installed in the IDE. The value of the `author` key is by default empty. -The `editorScheme` section will be addressed in [Adding a Custom Editor Scheme](themes_extras.md#adding-a-custom-editor-scheme) -The `ui` section will be addressed in [Customizing UI Control Colors](themes_customize.md#customizing-ui-controls). +The `editorScheme` section will be addressed in [Adding a Custom Editor Scheme](themes_extras.md#adding-a-custom-editor-scheme) +The `ui` section will be addressed in [Customizing UI Control Colors](themes_customize.md#customizing-ui-controls). -The Wizard also creates a `themeProvider` declaration in the `` section of the plugin's `plugin.xml` file. +The Wizard also creates a `themeProvider` declaration in the `` section of the plugin's `plugin.xml` file. This declaration binds the Theme description file to a theme provider extension using a generated unique `id`. ```xml @@ -94,13 +94,13 @@ This declaration binds the Theme description file to a theme provider extension > **WARNING** Do not modify or re-use an existing value of the generated `id` attribute. -At this point, the UI Theme `theme_basics` is a valid UI Theme. -Its plugin can be built and tested in IntelliJ Platform-based IDEs, giving the user the opportunity to select _theme_basics_ in the [Theme](https://www.jetbrains.com/help/idea/settings-appearance.html) _Preferences_ dropdown. +At this point, the UI Theme `theme_basics` is a valid UI Theme. +Its plugin can be built and tested in IntelliJ Platform-based IDEs, giving the user the opportunity to select _theme_basics_ in the [Theme](https://www.jetbrains.com/help/idea/settings-appearance.html) _Preferences_ dropdown. The custom Theme looks exactly like the IntelliJ IDEA default `Light` Theme, but it is a valid custom Theme. ### Completing the Default UI Theme Description File The default UI Theme definition can be directly edited to add or change some of the values for the default keys, if desired: The following values can be changed directly in the Theme (`*.theme.json`) description file: * The value of the `dark` key can be changed to `true`, which would switch the basis of the Theme to _Darcula_ instead of _Light_. -* The value of the `author` key, which defaults to an empty string, can be set to a `String` literal. +* The value of the `author` key, which defaults to an empty string, can be set to a `String` literal. In the case of the `theme_basics` code sample, it is set to "IntelliJ Platform SDK". diff --git a/reference_guide/ui_themes/themes_customize.md b/reference_guide/ui_themes/themes_customize.md index 21fa8102a..185aab726 100644 --- a/reference_guide/ui_themes/themes_customize.md +++ b/reference_guide/ui_themes/themes_customize.md @@ -15,28 +15,28 @@ title: Customizing UI Themes - Icons and UI Controls } -A UI Theme is customized by adding information to the UI Theme description file that overrides the base (_Light_ or _Darcula_) UI Theme. +A UI Theme is customized by adding information to the UI Theme description file that overrides the base (_Light_ or _Darcula_) UI Theme. ## Introduction to UI Theme Description File Syntax -The syntax of a Theme description file follows the JSON open-standard file format of key-value pairs. -The minimum valid default file is the output of the [DevKit Theme Wizard](themes.md#creating-a-ui-theme-with-the-devkit-theme-wizard). +The syntax of a Theme description file follows the JSON open-standard file format of key-value pairs. +The minimum valid default file is the output of the [DevKit Theme Wizard](themes.md#creating-a-ui-theme-with-the-devkit-theme-wizard). Adding key-value pairs customizes a Theme. -UI Theme key-value pairs often use a color as the `value`. +UI Theme key-value pairs often use color as the `value`. Colors are defined by six-digit RGB or eight-digit RGBA hexadecimal notation. ### UI Theme Reference Implementations When learning new syntax, it is often useful to have some existing implementations for reference. For example, refer to the [Theme description file](upsource:///platform/platform-resources/src/themes/HighContrast.theme.json) for the IntelliJ IDEA _High Contrast_ Theme. -It may also be helpful to review some of the [UI Themes available](https://plugins.jetbrains.com/search?headline=164-theme&tags=Theme) at the JetBrains Plugins Repository. +It may also help to review some of the [UI Themes available](https://plugins.jetbrains.com/search?headline=164-theme&tags=Theme) at the JetBrains Plugins Repository. ## Defining Named Colors Colors can always be defined individually as six-digit RGB or eight-digit RGBA hexadecimal notation. However, Theme definitions often use the same color in multiple places. Maintaining a Theme is more manageable if _Named Colors_ are globally defined in a `colors {}` block as part of the `*.theme.json` file. After that, the Named Color can be used instead of a hexadecimal description of the color. -For example, defining the Named Color `basicBackground` and then using it to set the background color for panels. -(Don't be concerned with the `"ui"` syntax in the example below, it will be discussed in [Custom UI Control Colors](#custom-ui-control-colors).) +For example, defining the Named Color `basicBackground` and then using it to set the background color of panels. +(Don't be concerned with the `"ui"` syntax in the example below; it will be discussed in [Custom UI Control Colors](#custom-ui-control-colors).) ```json { @@ -55,14 +55,14 @@ For example, defining the Named Color `basicBackground` and then using it to set ``` ## Customizing Icons -UI themes can customize the color of default IntelliJ Platform UI icons, or substitute custom icons for the default ones. +UI themes can customize the color of default IntelliJ Platform UI icons or substitute custom icons for the default ones. Customization is done by adding an `"icons": {}` section to the Theme description file. ### Overriding the Global Color of Icons -Default global icon colors are customized by adding key-value pairs to a `"ColorPalette": {}` section. +Default global icon colors are customized by adding key-value pairs to a `"ColorPalette": {}` section. The `ColorPalette` must be inserted in the `icons` section. -In the following example the `key` - the default red color (#DB5860) used for `Action` icons in the _Light_ Theme - is overridden to the `value` of a different color (#D61A26): +In the following example, the `key` - the default red color (#DB5860) used for `Action` icons in the _Light_ Theme - is overridden to the `value` of a different color (#D61A26): ```json { @@ -72,29 +72,28 @@ In the following example the `key` - the default red color (#DB5860) used for `A } } } -``` +``` This color substitution is applied throughout the IDE UI. ### Custom Icon Palette Colors -Icon Palettes are predefined UI Theme color keys, each describing a single color in an `Actions` or `Objects` context. +Icon Palettes are predefined UI Theme color keys that describe a single color in an `Actions` or `Objects` context. #### Icon Colors in "Actions" and "Objects" Contexts -IntelliJ Platform has default icon colors defined for `Actions` and `Objects` contexts. -* `Actions` are Theme keys for icons that appear in the context of toolbars, and represent actions such as _Compile_, _Run_, or _Debug_. +IntelliJ Platform has default icon colors defined for `Actions` and `Objects` contexts. +* `Actions` are Theme keys for icons that appear in the context of toolbars, and represent actions such as _Compile_, _Run_, or _Debug_. * `Objects` are Theme keys for icons that appear in the contexts of lists and trees, and represent entities like files, symbols, or run and debug configurations. -The [JetBrains Platform UI Guideline for Icons](https://jetbrains.design/intellij/principles/icons/) -defines the default hexadecimal RGB values of colors for `Actions` and `Objects` keys. +The [JetBrains Platform UI Guideline for Icons](https://jetbrains.design/intellij/principles/icons/) defines the default hexadecimal RGB values of colors for `Actions` and `Objects` keys. Note that this document refers to `Objects` keys as "Noun icons." #### Customizing "Actions" and "Objects" Icon Colors An icon Palette color is customized by adding an `Actions` or `Objects` `key` and custom color `value` to the `"ColorPalette": {}` section in a Theme description file. -The list of available icon `Actions` and `Objects` keys are provided by the completion popup in the editor: +The list of available icon `Actions` and `Objects` keys are provided by the editor's completion popup: ![Color Palette Popup](img/theme_colorpalette_popup.png){:width="600px"} -For example, the following key-value pair changes the color for all blue-colored icons on toolbars to the color #5BC0DE: +For example, the following key-value pair changes the color for all blue-colored icons on toolbars to the color `#5BC0DE`: ```json { @@ -106,23 +105,23 @@ For example, the following key-value pair changes the color for all blue-colore } ``` -This more specific change to the `Actions.Blue` color overrides the default definition. -It will also, in the narrower context of blue `Actions` icons, supersede any global color overrides of the default blue icon color. +This more specific change to the `Actions.Blue` color overrides the default definition. +In the narrower context of blue `Actions` icons, it will also supersede any global color overrides of the default blue icon color. ### Custom Icons -The default IntelliJ Platform UI icons can be replaced by custom icons. -The file format for icons is SVG. -The [JetBrains Platform UI Guideline for Icons](https://jetbrains.design/intellij/principles/icons/) has detailed specifications for icons. +The default IntelliJ Platform UI icons can be replaced by custom icons. +The file format for icons is SVG. +The [JetBrains Platform UI Guideline for Icons](https://jetbrains.design/intellij/principles/icons/) has detailed specifications for icons. -An icon replacement is described within the `icon {}` section of a Theme description file. -Note that icon replacement key-value pairs appear outside of the `ColorPalette` section. +An icon replacement is described within the `icon {}` section of a Theme description file. +Note that icon replacement key-value pairs appear outside of the `ColorPalette` section. For icon substitutions, the `key` is the path to the default icon image. -This path is derived from the `AllIcons.[Group].[IconName]` path in icon section reported by the [UI Inspector](/reference_guide/internal_actions/internal_ui_inspector.md). +This path is derived from the `AllIcons.[Group].[IconName]` path in icon section reported by the [UI Inspector](/reference_guide/internal_actions/internal_ui_inspector.md). -For example, the _Build_ (hammer) icon in the toolbar has the path `Allcons.Actions.Compile` as reported by the UI Inspector. -Therefore the `key` for the _Build_ icon is `/actions/compile.svg`. -The `value` is the file name of the replacement icon, located in the `resources` folder of the UI Theme plugin project: +For example, the _Build_ (hammer) icon in the toolbar has the path `Allcons.Actions.Compile` as reported by the UI Inspector. +Therefore the `key` for the _Build_ icon is `/actions/compile.svg`. +The `value` is the replacement icon's file name, located in the `resources` folder of the UI Theme plugin project: ```json { @@ -135,27 +134,27 @@ The `value` is the file name of the replacement icon, located in the `resources` The color of a replaced icon takes precedence over any `ColorPalette` overrides. ## Customizing UI Controls -UI Themes can change the appearance of more general controls in the IntelliJ Platform UI. +UI Themes can change the appearance of more general controls in the IntelliJ Platform UI. Examples of these controls are labels, buttons, checkboxes, trees, lists, and menus. ### Custom UI Control Colors -The custom color of a UI control is specified by adding a key-value pair to the `"ui": {}` section of a Theme description file. +A UI control's custom color is specified by adding a key-value pair to the `"ui": {}` section of a Theme description file. A UI control `key` has the compound format `element.property`, where: -* `element` is the type (label, checkbox, etc.,) of the UI control. +* `element` is the type (label, checkbox, etc.) of the UI control. * `property` is how the color is applied. Examples include `foreground`, `background`, and `errorForeground `. -Note that some UI control keys have more than two parts, for example `Popup.Advertiser.foreground` or `ScrollBar.Mac.Transparent.thumbColor`. +Note that some UI control keys have more than two parts, for example, `Popup.Advertiser.foreground` or `ScrollBar.Mac.Transparent.thumbColor`. The full key must be used to customize that specific button control. -However, for other purposes the first section can be considered the `element`, and the last section considered the `property`. +However, for other purposes, the first section can be considered the `element`, and the last section considered the `property`. -Methods for finding UI control keys are in the [Finding Attribute Keys for UI Controls](#finding-attribute-keys-for-ui-controls) section. +Methods for finding UI control keys are in the [Finding Attribute Keys for UI Controls](#finding-attribute-keys-for-ui-controls) section. #### Customizing All UI Control Colors with the Same Property -All UI Controls that have the same `property` portion of their key can be set to the same color. -This customization is done using the wildcard `"*": {}` section in the Theme description file. -A key-value pair is inserted in this section, but only the `property` portion of the key is specified. -The `value` is the custom color. +All UI Controls with the same `property` portion of their key can be set to the same color. +This customization is done using the wildcard `"*": {}` section in the Theme description file. +A key-value pair is inserted in this section, but only the `property` portion of the key is specified. +The `value` is the custom color. The following example would change the default background color to #AED7E3 for all UI controls: @@ -172,9 +171,9 @@ The following example would change the default background color to #AED7E3 for a Note that the wildcard `"*": {}` section must be within the `"ui": {}` section. #### Customizing the Color of Specific UI Control Types -The color of a specific UI control types are changed by adding a key-value pair to the `"ui": {}` section of a Theme description file. -The `key` is the full `element.property` format and the `value` is the custom color. - +The color of a specific UI control type is changed by adding a key-value pair to the `"ui": {}` section of a Theme description file. +The `key` is the full `element.property` format, and the `value` is the custom color. + The following example sets the background color for all labels to the color #F6E9C9 ```json @@ -188,17 +187,17 @@ The following example sets the background color for all labels to the color #F6E } ``` -The `Label.background` entry supersedes, in the narrower context of label backgrounds, any default color as well as any wildcard color assigned to backgrounds. +The `Label.background` entry supersedes, in the narrower context of label backgrounds, any default color, and any wildcard color assigned to backgrounds. #### Customizing the Color of UI Tabs UI Tab colors are changed by [key-value pairs](#custom-ui-control-colors) in a Theme description file. There are two implementations of tabs in the IntelliJ Platform: -* Editor Tabs, which e.g., represent open files in the [Editor window](https://www.jetbrains.com/help/idea/using-code-editor.html), and in [Tool Window bars](https://www.jetbrains.com/help/idea/tool-windows.html#bars_and_buttons). -* Tabbed Panes, which e.g., are used for the [Run/Debug Configurations dialog](https://www.jetbrains.com/help/idea/run-debug-configurations-dialog.html). +* Editor Tabs, which represent open files in the [Editor window](https://www.jetbrains.com/help/idea/using-code-editor.html), and in [Tool Window bars](https://www.jetbrains.com/help/idea/tool-windows.html#bars_and_buttons). +* Tabbed Panes, which are used for the [Run/Debug Configurations dialog](https://www.jetbrains.com/help/idea/run-debug-configurations-dialog.html). The control keys for UI Tabs were expanded from release 2019.1 to 2019.2 of the IntelliJ Platform. -The 2019.1 release control keys are compatible with release 2019.2 and later versions of the IntelliJ Platform. +The 2019.1 release control keys are compatible with release 2019.2 and later versions of the IntelliJ Platform. | Release 2019.1 Element | Release 2019.2 Element | Description of Release 2019.2 Element | |------|---------|---------| @@ -210,11 +209,11 @@ The 2019.1 release control keys are compatible with release 2019.2 and later ver | **`Plugins.Tab`** | **`TabbedPane`** | Use `TabbedPane` instead. | | **`SearchEverywhere.Tab`** | **`SearchEverywhere.Tab`** | No change. | -Methods for identifying UI control keys are in the [Finding Attribute Keys for UI Controls](#finding-attribute-keys-for-ui-controls) section. +Methods for identifying UI control keys are in the [Finding Attribute Keys for UI Controls](#finding-attribute-keys-for-ui-controls) section. For example, here is an excerpt from the IntelliJ Platform [High Contrast Theme](upsource:///platform/platform-resources/src/themes/HighContrast.theme.json): Note that a Theme file can mix versions of `property` identifiers: -* The first three `property` entries are recognized by release 2019.1, and ignored by subsequent releases because they are defined by new `property` identifiers. +* The first three `property` entries are recognized by release 2019.1 and ignored by subsequent releases because they are defined by new `property` identifiers. * The `underlineColor` `property` is recognized by release 2019.1 and subsequent releases. * The `underlineHeight` `property` was introduced in release 2019.2, and is ignored by previous releases. * The `underlinedTabBackground` `property` was introduced in release 2019.2, replaces the 2019.1 `selectedBackground`, and is ignored by previous releases. @@ -224,7 +223,7 @@ Note that a Theme file can mix versions of `property` identifiers: { "ui": { "EditorTabs": { - "selectedForeground": "#FFFFFF", + "selectedForeground": "#FFFFFF", "selectedBackground": "#0e5d73", "inactiveMaskColor": "#000000FF", @@ -239,19 +238,19 @@ Note that a Theme file can mix versions of `property` identifiers: ``` ### Customizing the Borders of UI Controls -The color and geometry of borders used in UI controls can be customized by key-value pairs in a Theme description file. +The color and geometry of borders used in UI controls can be customized by key-value pairs in a Theme description file. The format of keys for borders is `element.property`, where: -* `element` is the type of UI control containing a border, such as a window or a popup menu. +* `element` is the type of UI control containing a border, such as a window or a popup menu. * `property` is the desired border appearance, for example: - * `border` is the border width (in pixels) specified as top, left, bottom, and right widths. + * `border` is the border width (in pixels) specified as a top, left, bottom, and right widths. Border color is also (optionally) specified as hexadecimal RGB, e.g. "E6E6E6" with no "#" character. - * `borderInsets` is the inset distance (in pixels) from the edge of the `element` to the border. - It is specified as top, left, bottom, and right insets. + * `borderInsets` is the inset distance (in pixels) from the edge of the `element` to the border. + It is specified as top, left, bottom, and right insets. -Methods for identifying UI control keys are in the [Finding Attribute Keys for UI Controls](#finding-attribute-keys-for-ui-controls) section. +Methods for identifying UI control keys are in the [Finding Attribute Keys for UI Controls](#finding-attribute-keys-for-ui-controls) section. #### Customizing the Border Appearance of Specific UI Controls -The appearance of borders for specific UI control types are customized by adding a key-value pair to the `"ui": {}` section of a Theme description file. +Adding a key-value pair to the `"ui": {}` section of a Theme description file customizes the appearance of borders for specific UI control types. The following example sets a new border width and color for all windows: @@ -263,26 +262,25 @@ The following example sets a new border width and color for all windows: } ``` -In this example the customized border supersedes the default definition and -any global color override. +In this example, the customized border supersedes the default definition and any global color override. ## Finding Attribute Keys for UI Controls -There are hundreds of UI control `element.property` keys defined in the IntelliJ Platform UI. -Some keys and strategies for applying them can be gleaned from the [UI Theme reference implementations](#UI-Theme-Reference-Implementations). +There are hundreds of UI control `element.property` keys defined in the IntelliJ Platform UI. +Some keys and strategies for applying them can be gleaned from the [UI Theme reference implementations](#UI-Theme-Reference-Implementations). For a general search, here some suggested methods for locating UI control keys. ### Finding a UI Control Key Using Code Completion in the Editor -The preferred method of finding UI control keys is to use the [Code Completion](https://www.jetbrains.com/help/idea/auto-completing-code.html#Auto-Completing_Code.xml) feature in the editor. -Note that some keys presented by the code completion feature may be deprecated. +The preferred method of finding UI control keys is to use the [Code Completion](https://www.jetbrains.com/help/idea/auto-completing-code.html#Auto-Completing_Code.xml) feature in the editor. +Note that some keys presented by the code completion feature may be deprecated. New entries in the `"ui": {}` section will invoke the code completion popup, as shown below: ![UI Control Key Code Completion](img/uit_control_complete.png) Beginning with version 2019.2 of the IntelliJ Platform, the editor has added features for Code Completion and [Quick Documentation](https://www.jetbrains.com/help/idea/viewing-reference-information.html#inline-quick-documentation) to show the release in which a UI control key began to be supported. It appears as the _Since_ attribute in editor popups. -In the Quick Documentation popup the format is e.g. _Since: 2019.2_. -The Code Completion popup is similar, but it the format is e.g. _[Since 2019.2]_. +In the Quick Documentation popup, the format is e.g., _Since: 2019.2_. +The Code Completion popup is similar, but the format is e.g., _[Since 2019.2]_. ### Finding a UI Control Key Using Laf Defaults UI -Using the [Laf Defaults](/reference_guide/internal_actions/internal_ui_laf_defaults.md) inspector, enter the `element` portion of the key. +Using the [Laf Defaults](/reference_guide/internal_actions/internal_ui_laf_defaults.md) inspector, enter the `element` portion of the key. The Laf Defaults inspector will prompt with a list of UI Control keys and their default color. diff --git a/reference_guide/ui_themes/themes_extras.md b/reference_guide/ui_themes/themes_extras.md index be06d6e19..cd19d2585 100644 --- a/reference_guide/ui_themes/themes_extras.md +++ b/reference_guide/ui_themes/themes_extras.md @@ -4,22 +4,22 @@ title: UI Themes - Editor Schemes and Background Images UI Themes can also provide custom color and font settings, as well as custom images for display in the IDE application window. - + ## Adding a Custom Editor Scheme -Users of IntelliJ Platform-based IDEs, such as Intellij IDEA, can set preferences to configure the colors and fonts used in the Editor. +Users of IntelliJ Platform-based IDEs, such as Intellij IDEA, can set preferences to configure the colors and fonts used in the Editor. These custom color and font settings are called _Editor Color Schemes_. ### Creating a Custom Editor Scheme Using Settings/Preferences Custom editor color schemes can be specified and exported using the IDE _Settings/Preferences_ dialog. Note that editor [Colors and Fonts](https://www.jetbrains.com/help/idea/configuring-colors-and-fonts.html), and [Colors for Version Control File Status](https://www.jetbrains.com/help/idea/file-status-highlights.html) are customized in different sections of _Settings/Preferences_. -Use the following procedure to customize an editor color scheme for a UI Theme: -* Create the desired custom editor color scheme using the IDE preferences. +Use the following procedure to customize an editor color scheme for a UI Theme: +* Create the desired custom editor color scheme using the IDE preferences. * Export the custom editor color scheme to the desired file name. In this example, the file is exported to `Lightning.icls` * Once exported, change the file extension from `*.icls` to `*.xml`. In this example, the result is `Lightning.xml`. -* See [Customizing Editor Scroll Bar Colors](#customizing-editor-scroll-bar-colors) to change the colors of editor scroll bars. +* See [Customizing Editor Scroll Bar Colors](#customizing-editor-scroll-bar-colors) to change the colors of editor scroll bars. ### Incorporating the Editor Color Scheme in the Custom UI Theme The next step is to add the color scheme to the UI Theme plugin project: @@ -83,7 +83,7 @@ At this time there isn't code completion functionality for changing custom color #### Editor Scroll Bar Attribute Name Format The typical format of a scroll bar `name` attribute is `ScrollBar.usage`, where `usage` describes where the color is to be applied. -In some cases `usage` itself can be compound such as `ScrollBar.Mac.Transparent.thumbColor`. +In some cases `usage` itself can be compound such as `ScrollBar.Mac.Transparent.thumbColor`. In these compound cases, the last portion of the compound `usage` still describes where the color is to be applied. Note that the following example snippet uses an eight-digit hexadecimal color `value` to give `ScrollBar.Mac.thumbColor` transparency: @@ -96,54 +96,54 @@ Note that the following example snippet uses an eight-digit hexadecimal color `v ``` #### Editor Scroll Bar Attribute Names -A list of scroll bar `name` attributes is in the [High Contrast editor scheme](upsource:///platform/platform-resources/src/themes/highContrastScheme.xml) file. +A list of scroll bar `name` attributes is in the [High Contrast editor scheme](upsource:///platform/platform-resources/src/themes/highContrastScheme.xml) file. These name attributes cannot be accessed from anywhere in the IDE UI at this time, so they must be manually added to an editor color scheme XML file. The following list explains the `usage` format of the `name` attribute, i.e. where a custom scroll bar color is applied: -* `*.trackColor` — The scroll bar thumb moves across this area. +* `*.trackColor` — The scroll bar thumb moves across this area. At this time the vertical scrollbar track color and transparency cannot be customized. * `*.thumbColor` — The movable rectangle that corresponds to the visible content's size. * `*.thumbBorderColor` — The thumb border. -* `*.hoverTrackColor` — Same `usage` as above but for hover. +* `*.hoverTrackColor` — Same `usage` as above but for hover. At this time the vertical scrollbar hover track color and transparency cannot be customized. * `*.hoverThumbColor` — Same `usage` as above but for hover. * `*.hoverThumbBorderColor` — Same `usage` as above but for hover. -The `name` attribute patterns are enumerated below. +The `name` attribute patterns are enumerated below. **Platform Independent Name Attributes** -The horizontal scroll bar background color is set by `ScrollBar.background`. +The horizontal scroll bar background color is set by `ScrollBar.background`. This background color is visible only if the horizontal scroll bar's `*.trackColor` has transparency. At this time the vertical scrollbar background color cannot be customized. -**Windows/Linux Name Attributes** +**Windows/Linux Name Attributes** The `name` attributes for Windows and Linux scroll bars have the pattern `ScrollBar.Transparent.*`, where the wildcard portion corresponds to the `usage` definitions above. -**macOS Name Attributes** +**macOS Name Attributes** -The `name` attribute pattern for the vertical scroll bar is `ScrollBar.Mac.*`. +The `name` attribute pattern for the vertical scroll bar is `ScrollBar.Mac.*`. The `name` attribute pattern for the horizontal scroll bar depends on the macOS preferences _Show scroll bars_ setting: * `ScrollBar.Mac.*` when the _Always_ setting is selected. - * `ScrollBar.Mac.Transparent.*` when the _When scrolling_ setting is selected. + * `ScrollBar.Mac.Transparent.*` when the _When scrolling_ setting is selected. The wildcard portion of these patterns corresponds to the `usage` definitions above. ## Adding a Custom Background Image -The IDE supports setting an image as a background in the application window. +The IDE supports setting an image as a background in the application window. Users can do this manually in [Preferences](https://www.jetbrains.com/help/idea/setting-background-image.html). UI Themes support specifying a background image as a key-value pair in the `"background": {}` section of a Theme description file: * The `image` key uses the file name of the image as the value. -The background image is placed in the UI Theme plugin project's resources folder. -* The `transparency` key uses a `value` of 1-100. +The background image is placed in the UI Theme plugin project's resources folder. +* The `transparency` key uses a `value` of 1-100. A `value` of 100 is opaque. * The `fill` key uses a value of `scale`, meaning to expand the image to fill the space as the window gets resized. -* The `anchor` key uses a value of `center`, meaning to locate the center of the image in the center of the window. +* The `anchor` key uses a value of `center`, meaning to locate the center of the image in the center of the window. The following example adds an image of the Austrian countryside to the _Theme Basics_ @@ -163,4 +163,4 @@ Theme description file: "anchor": "center" } } -``` \ No newline at end of file +``` diff --git a/reference_guide/ui_themes/themes_intro.md b/reference_guide/ui_themes/themes_intro.md index 705da1cca..f8d24745e 100644 --- a/reference_guide/ui_themes/themes_intro.md +++ b/reference_guide/ui_themes/themes_intro.md @@ -6,8 +6,8 @@ title: Custom UI Themes Beginning with the 2019.1 release, custom UI Themes are supported. Custom UI Themes give designers control of the appearance of built-in UI elements. The [UI Themes available for download](https://plugins.jetbrains.com/search?headline=164-theme&tags=Theme) illustrate the creative possibilities. - -[Creating a new UI element](/user_interface_components/user_interface_components.md) for a plugin is distinctly different than Custom UI Themes. + +[Creating a new UI element](/user_interface_components/user_interface_components.md) for a plugin is distinctly different than Custom UI Themes. > **NOTE** Custom UI Themes are available beginning in version **2019.1**. @@ -16,4 +16,4 @@ This section discusses creating and customizing UI Themes: * [Customizing UI Themes](themes_customize.md) * [Adding Editor Schemes and Background Images](themes_extras.md) -For plugin developers, [Exposing Theme Metadata](themes_metadata.md) discusses the format of customization keys and information how to provide it to Theme authors. \ No newline at end of file +For plugin developers, [Exposing Theme Metadata](themes_metadata.md) discusses the format of customization keys and information how to provide it to Theme authors. diff --git a/reference_guide/ui_themes/themes_metadata.md b/reference_guide/ui_themes/themes_metadata.md index 5cc63ddfd..0a4c28cf3 100644 --- a/reference_guide/ui_themes/themes_metadata.md +++ b/reference_guide/ui_themes/themes_metadata.md @@ -14,25 +14,25 @@ title: Exposing Theme Metadata -All available UI Customization Keys that can be used in [Custom Themes](themes_customize.md) must be defined in a dedicated `*.themeMetadata.json` file which is registered via `com.intellij.themeMetadataProvider` extension point. +All available UI Customization Keys that can be used in [Custom Themes](themes_customize.md) must be defined in a dedicated `*.themeMetadata.json` file which is registered via `com.intellij.themeMetadataProvider` extension point. The following minimal sample demonstrates all details required when exposing UI customization keys of your plugin's UI. `/resources/META-INF/plugin.xml`: ```xml - + [...] - + [...]
``` `/resources/META-INF/MyPlugin.themeMetadata.json`: -```json +```json { "name": "My Plugin", "fixed": false, @@ -48,7 +48,7 @@ The following minimal sample demonstrates all details required when exposing UI } ] } -``` +``` ### Attributes - `name` - Human-readable name, e.g., plugin name @@ -59,11 +59,11 @@ The following minimal sample demonstrates all details required when exposing UI - `description` - Description to be shown to Theme authors editing `*.theme.json` files - `deprecated` - `true` when key is deprecated, please provide explanation and/or replacement in `description` if available - `source` - FQN of the underlying UI component implementation - - `since` - The release number (e.g. `[2019.2]`) when this UI customization key was exposed. + - `since` - The release number (e.g. `[2019.2]`) when this UI customization key was exposed. A release number prior to 2019.2 is valid. > **NOTE** Support for the `since` attribute began with version 2019.2, so this attribute is only displayed in versions 2019.2 and later. - + > **TIP** It is highly recommended to always provide a `description` entry, so Theme authors can understand usages. > **TIP** Do not remove existing keys, but deprecate them instead to help Theme authors upgrade their existing themes. @@ -73,7 +73,7 @@ Color keys can be used via `JBColor.namedColor()` providing defaults for Light a ```java private static final Color SECTION_HEADER_FOREGROUND = JBColor.namedColor("Plugins.SectionHeader.foreground", new JBColor(0x787878, 0x999999)); -``` +``` Other keys can be obtained via `javax.swing.UIManager#getXXX()` methods. @@ -126,19 +126,19 @@ If a part is common among several components, use the same name for it. Notable #### SubObject Use a subobject when creating keys for one of the following: -- An implementation variation. Usually has a similar set of UI property keys as the parent object. Examples: +- An implementation variation. Usually has a similar set of UI property keys as the parent object. Examples: - Default button: `Button.Default.background` - - Tool window notification: `Notification.ToolWindow.errorBackground` + - Tool window notification: `Notification.ToolWindow.errorBackground` - An internal smaller component of a complex component with its own UI and behavior. Examples: - Tool window tab: `ToolWindow.HeaderTab.inactiveBackground` - - The hint text at the bottom of a popup: `Popup.Advertiser.background` + - The hint text at the bottom of a popup: `Popup.Advertiser.background` #### Gradient Color If a component has a gradient color, add the words “start” and “end” for the beginning and ending of a gradient. Examples: - `Button.startBorderColor` / `Button.endBorderColor` - `SearchMatch.startBackground` / `SearchMatch.endBackground` -#### Capitalization +#### Capitalization Capitalize Object and SubObject. Use lowerCamelCase for property. #### Do Not Use @@ -148,11 +148,12 @@ Capitalize Object and SubObject. Use lowerCamelCase for property. | `Color` _as a separate word_ | `Color` | | `Outline` | `borderColor` | | `Text` | `Foreground` | -| `darcula` _and other look-and-feel names_ | _Omit_ | +| `darcula` _and other look-and-feel names_ | _Omit_ | #### Swing Legacy -Some color keys are not named according to the rules above. Such keys are inherited from Java Swing and cannot be renamed for compatibility reasons. +Some color keys are not named according to the rules above. +Such keys are inherited from Java Swing and cannot be renamed for compatibility reasons. Do not use naming patterns from the legacy keys. Examples of Swing keys: @@ -169,4 +170,5 @@ Metadata is split up as follows: New keys should be added to `IntelliJPlatform.themeMetadata.json` only (or corresponding "local" `*.themeMetadata.json` file of the plugin if applicable). -Please make sure to add a `description` and use `since` and `deprecated` attributes explained in [Attributes](#attributes). Respect [Key Naming Scheme](#key-naming-scheme) and keep alphabetical ordering of keys. +Please make sure to add a `description` and use `since` and `deprecated` attributes explained in [Attributes](#attributes). +Respect [Key Naming Scheme](#key-naming-scheme) and keep alphabetical ordering of keys. diff --git a/reference_guide/vcs_integration_for_plugins.md b/reference_guide/vcs_integration_for_plugins.md index 076fc48a5..a7106f450 100644 --- a/reference_guide/vcs_integration_for_plugins.md +++ b/reference_guide/vcs_integration_for_plugins.md @@ -9,104 +9,72 @@ This page gives an overview of the Version Control Integration API. ### FilePath -A [`FilePath`](upsource:///platform/platform-api/src/com/intellij/openapi/vcs/FilePath.java) -represents a path to a file or directory on disk or in the VCS repository. -Unlike a -[`VirtualFile`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java), -a `FilePath` can represent a path to a file which doesn't exist on disk. -The main difference between a `FilePath` and a -[`java.io.File`](https://docs.oracle.com/javase/8/docs/api/java/io/File.html) -is that a -`FilePath` caches the [`VirtualFile`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java) -corresponding to the path, so it can be retrieved without doing a VFS search. +A [`FilePath`](upsource:///platform/platform-api/src/com/intellij/openapi/vcs/FilePath.java) represents a path to a file or directory on disk or in the VCS repository. +Unlike a [`VirtualFile`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java), a `FilePath` can represent a path to a file which doesn't exist on disk. +The main difference between a `FilePath` and a [`java.io.File`](https://docs.oracle.com/javase/8/docs/api/java/io/File.html) is that a `FilePath` caches the [`VirtualFile`](upsource:///platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java) corresponding to the path, so it can be retrieved without doing a VFS search. -To create instances of -[`FilePath`](upsource:///platform/platform-api/src/com/intellij/openapi/vcs/FilePath.java), -the -[`VcsContextFactory`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/actions/VcsContextFactory.java) -API is used. +To create instances of [`FilePath`](upsource:///platform/platform-api/src/com/intellij/openapi/vcs/FilePath.java), the [`VcsContextFactory`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/actions/VcsContextFactory.java) API is used. It can be accessed as`PeerFactory.getInstance().getVcsContextFactory()` -`FilePath` representing paths in a VCS repository, rather than local paths, are created using -`VcsContextFactory.createFilePathOnNonLocal()`. The `FilePath.isNonLocal()` method returns `true` for such files. +`FilePath` representing paths in a VCS repository, rather than local paths, are created using `VcsContextFactory.createFilePathOnNonLocal()`. +The `FilePath.isNonLocal()` method returns `true` for such files. ### Revision Number -A -[`VcsRevisionNumber`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java) -represents a revision number of the file. -If the VCS stores revision numbers as simple integers, the standard -[`VcsRevisionNumber`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java). -Int implementation can be used. +A [`VcsRevisionNumber`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java) represents a revision number of the file. +If the VCS stores revision numbers as simple integers, the standard [`VcsRevisionNumber`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java) `Int` implementation can be used. If the VCS has a more complex format of revision numbers (like CVS, which uses a series of numbers delimited with dots), the plugin can provide a custom implementation. ### ContentRevision -A -[`ContentRevision`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/ContentRevision.java) -represents a particular revision of a file, which exists either locally or in a VCS repository. +A [`ContentRevision`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/ContentRevision.java) represents a particular revision of a file, which exists either locally or in a VCS repository. It has three main attributes: -* `FilePath` specifying the file of which this is a revision. If some version of the file exists locally, this should be a local path. - -* [`VcsRevisionNumber`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java) specifying the revision number of the revision, or `VcsRevisionNumber.NULL` if the revision exists only locally. - -* Content of the revision. +* `FilePath` specifying the file of which this is a revision. + If some version of the file exists locally, this should be a local path. +* [`VcsRevisionNumber`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java) specifying the revision number of the revision, or `VcsRevisionNumber.NULL` if the revision exists only locally. +* Content of the revision. The content is returned as string, and the VCS plugin is responsible for converting the binary file content to correct encoding. To detect the encoding automatically based on the IDE settings and the byte order mark, the method `CharsetToolkit.bytesToString()` can be used (this API is new in IDEA 7.0.2). Revisions of binary files can also be represented as BinaryContentRevision, which is a subclass of ContentRevision. For binary revisions, the result of getContent() is undefined, and getBinaryContent() can be used to retrieve the contents as a byte array. -A useful class which can be used to represent the current on-disk version of a particular file is -[`CurrentContentRevision`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/CurrentContentRevision.java). +A useful class which can be used to represent the current on-disk version of a particular file is [`CurrentContentRevision`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/CurrentContentRevision.java). ### FileStatus -A -[`FileStatus`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/vcs/FileStatus.java) -represents a status of a file in regard to VCS (unversioned, not changed, added, modified and so on). +A [`FileStatus`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/vcs/FileStatus.java) represents a status of a file in regard to VCS (unversioned, not changed, added, modified and so on). It determines the color used to render the name of the file in the UI. ### Change -A -[`Change`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/Change.java) -represents a single file operation (creation, modification, move/rename or deletion) from a VCS point of view. +A [`Change`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/Change.java) represents a single file operation (creation, modification, move/rename or deletion) from a VCS point of view. A Change can represent either a modification which the user has performed locally and not yet committed, a committed modification, or some other type of modification (for example, a shelved change or a difference between two arbitrary revisions). -A -[`Change`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/Change.java) -essentially consists of two content revisions: +A [`Change`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/Change.java) essentially consists of two content revisions: -* before revision (`null` if the *Change* represents file creation) - -* after revision (`null` if the *Change* represents file deletion) +* before revision (`null` if the *Change* represents file creation) +* after revision (`null` if the *Change* represents file deletion) A move or rename is represented by a Change where the before revision and the after revision have different file paths. -A custom file status can be specified for a -[`Change`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/Change.java) -if it represents a non-standard modification of the file (for example, a file which has been merged with conflicts). +A custom file status can be specified for a [`Change`](upsource:///platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/Change.java) if it represents a non-standard modification of the file (for example, a file which has been merged with conflicts). If a custom file status has not been specified, the status is calculated automatically from the change type. ### ChangeList -A -[`ChangeList`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeList.java) -represents a named group of related changes. +A [`ChangeList`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeList.java) represents a named group of related changes. There are two main kinds of changelists: -* [`LocalChangeList`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/LocalChangeList.java) represents a group of modifications done by a user locally. - If the VCS also supports the concept of changelists (like Perforce does), the VCS plugin can synchronize IDEA's local changelist structure with that of the VCS. - Otherwise, a local changelist is simply a subset of the files checked out or modified by the user. +* [`LocalChangeList`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/LocalChangeList.java) represents a group of modifications done by a user locally. + If the VCS also supports the concept of changelists (like Perforce does), the VCS plugin can synchronize IDEA's local changelist structure with that of the VCS. + Otherwise, a local changelist is simply a subset of the files checked out or modified by the user. +* [`CommittedChangeList`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/versionBrowser/CommittedChangeList.java) represents a set of modifications checked in to the VCS repository. + For VCSes which support atomic commit, every committed revision is represented by a CommittedChangeList. + For VCSes which use per-file commit (like CVS), the plugin can use heuristics to group a sequence of individual file commits into a + [`CommittedChangeList`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/versionBrowser/CommittedChangeList.java) -* [`CommittedChangeList`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/versionBrowser/CommittedChangeList.java) - represents a set of modifications checked in to the VCS repository. - For VCSes which support atomic commit, every committed revision is represented by a CommittedChangeList. - For VCSes which use per-file commit (like CVS), the plugin can use heuristics to group a sequence of individual file commits into a - [`CommittedChangeList`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/versionBrowser/CommittedChangeList.java) - -> **NOTE** The *Unversioned Files*, *Locally Deleted Files* etc. nodes in the *Changes* view are not actually changelists, and files under those nodes are not represented by Change objects. +> **NOTE** The *Unversioned Files*, *Locally Deleted Files*, etc., nodes in the *Changes* view are not actually change lists, and files under those nodes are not represented by `ChangeList` objects. ## Plugin Components @@ -131,48 +99,22 @@ Here `name` is the unique name of the VCS (this must match the string returned b ### ChangeProvider This component is responsible for tracking user changes to the working copy, and reporting these changes to the IntelliJ Platform core. -An implementation of this class is returned from -[`AbstractVcs.getChangeProvider()`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcs.java). +An implementation of this class is returned from [`AbstractVcs.getChangeProvider()`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcs.java). -The ChangeProvider works in tandem with -[`VcsDirtyScopeManager`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManager.java), -which is a component in IntelliJ Platform core. -[`VcsDirtyScopeManager`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManager.java) -keeps track of the 'dirty scope' - the set of files for which the VCS file status may be out of date. -Files are added to the dirty scope either when they are modified on disk, or when their VCS status is invalidated by an explicit call to -[`VcsDirtyScopeManager.fileDirty()`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManager.java) -or -[`VcsDirtyScopeManager.dirDirtyRecursively()`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManager.java). +The ChangeProvider works in tandem with [`VcsDirtyScopeManager`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManager.java), which is a component in IntelliJ Platform core. [`VcsDirtyScopeManager`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManager.java) keeps track of the 'dirty scope' - the set of files for which the VCS file status may be out of date. +Files are added to the dirty scope either when they are modified on disk, or when their VCS status is invalidated by an explicit call to [`VcsDirtyScopeManager.fileDirty()`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManager.java) or [`VcsDirtyScopeManager.dirDirtyRecursively()`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManager.java). -After some files have been added to the dirty scope, the dirty scope is passed to -[`ChangeProvider.getChanges()`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeProvider.java), -along with a -[`ChangelistBuilder`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangelistBuilder.java) -instance, which serves as a sink to which the -[`ChangeProvider`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeProvider.java) -feeds the data about the changed files. +After some files have been added to the dirty scope, the dirty scope is passed to [`ChangeProvider.getChanges()`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeProvider.java), along with a [`ChangelistBuilder`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangelistBuilder.java) instance, which serves as a sink to which the [`ChangeProvider`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeProvider.java) feeds the data about the changed files. This processing happens asynchronously in a background thread. -The -[`ChangeProvider`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeProvider.java) -can either iterate all files under the dirty scope using -[`VcsDirtyScope.iterate()`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScope.java), -or retrieve information about its contents using the `getDirtyFiles()` and `getDirtyDirectoriesRecursively()` methods. +The [`ChangeProvider`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeProvider.java) can either iterate all files under the dirty scope using [`VcsDirtyScope.iterate()`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScope.java), or retrieve information about its contents using the `getDirtyFiles()` and `getDirtyDirectoriesRecursively()` methods. If it is possible to retrieve the information about the local changes from the VCS in batch, it's strongly preferable to use the second method, as it scales much better for large working copies. -The -[`ChangeProvider`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeProvider.java) -reports data to ChangelistBuilder using the following methods: - -* `processChange()` is called for files which have been checked out (or modified if the VCS doesn't use an explicit checkout model), scheduled for addition or deletion, moved or renamed. - -* `processUnversionedFile()` is called for files which exist on disk, but are not managed by the VCS, not scheduled for addition, and not ignored through *.cvsignore* or a similar mechanism. - -* `processLocallyDeletedFile()` is called for files which exist in the VCS repository, but do not exist on disk and are not scheduled for deletion. - -* `processIgnoredFile()` is called for files which are not managed by the VCS but are ignored through *.cvsignore* or a similar mechanism. - -* `processSwitchedFile()` is called for files or directories for which the working copy corresponds to a different branch compared to the working copy of their parent directory. - This can be called for the same files for which processSwitchedFile() has already been called. - +The [`ChangeProvider`](upsource:///platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeProvider.java) reports data to ChangelistBuilder using the following methods: +* `processChange()` is called for files which have been checked out (or modified if the VCS doesn't use an explicit checkout model), scheduled for addition or deletion, moved or renamed. +* `processUnversionedFile()` is called for files which exist on disk, but are not managed by the VCS, not scheduled for addition, and not ignored through *.cvsignore* or a similar mechanism. +* `processLocallyDeletedFile()` is called for files which exist in the VCS repository, but do not exist on disk and are not scheduled for deletion. +* `processIgnoredFile()` is called for files which are not managed by the VCS but are ignored through *.cvsignore* or a similar mechanism. +* `processSwitchedFile()` is called for files or directories for which the working copy corresponds to a different branch compared to the working copy of their parent directory. + This can be called for the same files for which processSwitchedFile() has already been called. diff --git a/reference_guide/work_with_icons_and_images.md b/reference_guide/work_with_icons_and_images.md index 228d40ea5..77a8c25a0 100644 --- a/reference_guide/work_with_icons_and_images.md +++ b/reference_guide/work_with_icons_and_images.md @@ -3,18 +3,20 @@ title: Working with Icons and Images --- -Icons and images are used widely by IntelliJ Platform plugins. Plugins need icons mostly for actions, custom components renderers, tool windows, and so on. +Icons and images are used widely by IntelliJ Platform plugins. +Plugins need icons mostly for actions, custom components renderers, tool windows, and so on. > **NOTE** Plugin Icons, which represent a plugin itself, have different requirements than icons and images used within a plugin. -For more information see the [Plugin Icon](/basics/plugin_structure/plugin_icon_file.md) page. +For more information see the [Plugin Icon](/basics/plugin_structure/plugin_icon_file.md) page. + +> **TIP** Plugins should reuse existing platform icons whenever possible, see [`AllIcons`](upsource:///platform/util/src/com/intellij/icons/AllIcons.java). +> A detailed [design guideline](https://jetbrains.design/intellij/principles/icons/) is available for creating custom icons. -> **TIP** Plugins should reuse existing platform icons whenever possible, see [`AllIcons`](upsource:///platform/util/src/com/intellij/icons/AllIcons.java). A detailed [design guideline](https://jetbrains.design/intellij/principles/icons/) is available for creating custom icons. - ## How to organize and how to use icons? The best way to deal with icons and other image resources is to put them to a dedicated source root marked as *Resources Root*, say `icons` or `resources`. -The `getIcon()` method of [`IconLoader`](upsource:///platform/util/ui/src/com/intellij/openapi/util/IconLoader.java) can be used to access the icons. +The `getIcon()` method of [`IconLoader`](upsource:///platform/util/ui/src/com/intellij/openapi/util/IconLoader.java) can be used to access the icons. > **NOTE** The path to the icon passed in as argument to `IconLoader.getIcon()` must start with leading `/` @@ -42,7 +44,9 @@ Use these constants inside `plugin.xml` as well. Note that the package name `ico ## Image Formats -IntelliJ Platform supports Retina displays and has dark theme called Darcula. Thus, every icon should have a dedicated variant for Retina devices and Darcula theme. In some cases, you can skip dark variants if the original icon looks good under Darcula. +IntelliJ Platform supports Retina displays and has dark theme called Darcula. +Thus, every icon should have a dedicated variant for Retina devices and Darcula theme. +In some cases, you can skip dark variants if the original icon looks good under Darcula. Required icon sizes depend on the usage as listed in the following table: @@ -58,7 +62,9 @@ Required icon sizes depend on the usage as listed in the following table: As SVG icons can be scaled arbitrarily, they provide better results on HiDPI environments or when used in combination with bigger screen fonts (e.g., in presentation mode). -A base size denoting the size (in the user space) of the rendered image in 1x scale should be provided. The size is set via the `width` and `height` attributes omitting the size units. If unspecified, it defaults to 16x16 pixels. +A base size denoting the size (in the user space) of the rendered image in 1x scale should be provided. +The size is set via the `width` and `height` attributes omitting the size units. +If unspecified, it defaults to 16x16 pixels. A minimal SVG icon file: @@ -68,9 +74,12 @@ A minimal SVG icon file: ``` -The naming notation used for PNG icons (see below) is still relevant. However, the `@2x` version of an SVG icon should still provide the same base size. The icon graphics of such an icon can be expressed in more details via double precision. If the icon graphics are simple enough so that it renders perfectly in every scale, then the `@2x` version can be omitted. +The naming notation used for PNG icons (see below) is still relevant. +However, the `@2x` version of an SVG icon should still provide the same base size. +The icon graphics of such an icon can be expressed in more details via double precision. +If the icon graphics are simple enough so that it renders perfectly in every scale, then the `@2x` version can be omitted. -### PNG Format +### PNG Format > **NOTE** Please consider using SVG icons if your plugin targets 2018.2+. All icon files must be placed in the same directory following this naming pattern (replace `.png` with `.svg` for SVG icons): @@ -90,4 +99,3 @@ Here are examples of *toolWindowStructure.png* icon representations: | Darcula | `toolWindowStructure_dark.png` | ![Tool Window Structure, dark](img/toolWindowStructure_dark.png) | | Default + Retina | `toolWindowStructure@2x.png` | ![Tool Window Structure, retina](img/toolWindowStructure@2x.png) | | Darcula + Retina | `toolWindowStructure@2x_dark.png` | ![Tool Window Structure, retina, dark](img/toolWindowStructure@2x_dark.png) | - diff --git a/sdkdocs-template b/sdkdocs-template index 6232a70c3..a2817eb24 160000 --- a/sdkdocs-template +++ b/sdkdocs-template @@ -1 +1 @@ -Subproject commit 6232a70c3b68c85b1d718ac8fb4feb8b60576b58 +Subproject commit a2817eb243d257ef6d414e45f1fde4c20aaa41a1 diff --git a/tutorials/action_system.md b/tutorials/action_system.md index 5c5c046e7..1dce706dc 100644 --- a/tutorials/action_system.md +++ b/tutorials/action_system.md @@ -3,14 +3,10 @@ title: IntelliJ Action System Tutorial --- -This tutorial leads you through a series of steps which show how to create, register, and customize custom actions and action groups. -By registering actions, you can add your own menu items, toolbar buttons and keyboard shortcuts to the IDE user interface. +This tutorial leads you through a series of steps which show how to create, register, and customize custom actions and action groups. +By registering actions, you can add your own menu items, toolbar buttons and keyboard shortcuts to the IDE user interface. * [Creating Actions](action_system/working_with_custom_actions.md) * [Grouping Actions](action_system/grouping_action.md) The source code for the [`action_basics`](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/action_basics) code sample is used throughout this tutorial. - - - - diff --git a/tutorials/action_system/grouping_action.md b/tutorials/action_system/grouping_action.md index 64bf38783..fa8e612e0 100644 --- a/tutorials/action_system/grouping_action.md +++ b/tutorials/action_system/grouping_action.md @@ -18,7 +18,7 @@ The group is based on a default IntelliJ Platform implementation. ### Creating Simple Groups Grouping can be registered by adding a `` element to the `` section of a plugin's `plugin.xml` file. -This example has no `class` attribute in the `` element because the IntelliJ Platform framework will supply a default implementation class for the group. +This example has no `class` attribute in the `` element because the IntelliJ Platform framework will supply a default implementation class for the group. This default implementation is used if a set of actions belonging to the group is static, i.e., does not change at runtime, which is the majority of cases. The `id` attribute must be unique, so incorporating the plugin ID or package name is the best practice. @@ -33,8 +33,8 @@ See [Registering Actions in plugin.xml](/basics/action_system.md#registering-act ``` ### Binding Action Groups to UI Components -The following sample shows how to use an `` element to place a custom action group relative to an entry in the **Tools** menu. -The attribute `relative-to-action` references the action `id` for `PopupDialogAction`, which is not a native IntelliJ menu entry. +The following sample shows how to use an `` element to place a custom action group relative to an entry in the **Tools** menu. +The attribute `relative-to-action` references the action `id` for `PopupDialogAction`, not a native IntelliJ menu entry. Rather `PopupDialogAction` is defined in the same [`plugin.xml`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/action_basics/src/main/resources/META-INF/plugin.xml) file. This group is placed after the single entry for the action `PopupDialogAction`, as defined in the tutorial [Creating Actions](working_with_custom_actions.md#registering-an-action-with-the-new-action-form). @@ -45,9 +45,9 @@ This group is placed after the single entry for the action `PopupDialogAction`, ``` ### Adding a New Action to the Static Grouped Actions -The `PopupDialogAction` implementation will be reused and registered in the newly created static group. +The `PopupDialogAction` implementation will be reused and registered in the newly created static group. The `id` attribute for the reused `PopupDialogAction` implementation is set to a unique value, `org.intellij.sdk.action.GroupPopDialogAction`. -This value differentiates this new `` entry from the `id` previously used to register this action implementation in the [Creating Actions](working_with_custom_actions.md#registering-an-action-with-the-new-action-form) tutorial. +This value differentiates this new `` entry from the `id` previously used to register this action implementation in the [Creating Actions](working_with_custom_actions.md#registering-an-action-with-the-new-action-form) tutorial. A unique `id` supports reuse of action classes in more than one menu or group. The action in this group will display the menu text "A Group Action". @@ -60,29 +60,28 @@ The action in this group will display the menu text "A Group Action". ``` -After performing the steps described above the action group and its content will be available in the **Tools** menu. +After performing the steps described above, the action group and its content will be available in the **Tools** menu. The underlying `PopupDialogAction` implementation is reused for two entries in the **Tools** menu: * Once for the top menu entry **Tools \| Pop Dialog Action** with the action `id` equal to `org.intellij.sdk.action.PopupDialogAction` as set in the [Creating Actions](/tutorials/action_system/working_with_custom_actions.md#registering-an-action-with-the-new-action-form) tutorial. * A section time for the menu entry **Tools \| Static Grouped Actions \| A Group Action** with the action `id` equal to `org.intellij.sdk.action.GroupPopDialogAction`. ![Simple Action Group](img/grouped_action.png){:width="550px"} - - + + ## Implementing Custom Action Group Classes In some cases, the specific behavior of a group of actions needs to depend on the context. -The solution is analagous to making a [single action entry dependent on context](working_with_custom_actions.md#extending-the-update-method). +The solution is analagous to making a [single action entry dependent on context](working_with_custom_actions.md#extending-the-update-method). The steps below show how to make a group of actions available and visible if certain conditions are met. -In this case, the condition is having an instance of an editor is available. +In this case, the condition is having an instance of an editor is available. This condition is needed because the custom action group is added to an IntelliJ menu that is only enabled for editing. ### Extending DefaultActionGroup The [`DefaultActionGroup`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java) is an implementation of [`ActionGroup`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionGroup.java). The `DefaultActionGroup` class is used to add child actions and separators between them to a group. -This class is used if a set of actions belonging to the group does not change at runtime, which is the majority of cases. +This class is used if a set of actions belonging to the group does not change at runtime. -As an example, extend [`DefaultActionGroup`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java) -to create the `CustomDefaultActionGroup` class in the `action_basics` code sample: +As an example, extend [`DefaultActionGroup`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java) to create the `CustomDefaultActionGroup` class in the `action_basics` code sample: ```java public class CustomDefaultActionGroup extends DefaultActionGroup { @@ -94,7 +93,7 @@ to create the `CustomDefaultActionGroup` class in the `action_basics` code sampl ``` ### Registering the Custom Action Group -As in the case with the static action group, the action `` should be declared in the `` section of the `plugin.xml` file, for example, the [action_basics](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/action_basics/src/main/resources/META-INF/plugin.xml) plugin. +As in the case with the static action group, the action `` should be declared in the `` section of the `plugin.xml` file, for example, the [action_basics](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/action_basics/src/main/resources/META-INF/plugin.xml) plugin. For demonstration purposes, this implementation will use localization. The `` element declaration below shows: @@ -118,13 +117,13 @@ The `` element declaration below shows: ``` ### Adding Actions to the Custom Group -As in [Static Grouped Actions](#adding-a-new-action-to-the-static-grouped-actions), the `PopupDialogAction` action is added as an `` element in the `` element. +As in [Static Grouped Actions](#adding-a-new-action-to-the-static-grouped-actions), the `PopupDialogAction` action is added as an `` element in the `` element. In the `` element declaration below: * The `class` attribute in the `` element has the same FQN to reuse this action implementation. * The `id` attribute is unique to distinguish it from other uses of the implementation in the Action System. * The `text` and `description` attributes are omitted in the `` declaration; they are instead defined using the localization resource bundle. * The SDK icon is declared for use with this action. - + ```xml ``` -> **WARNING** If a`` element's `class` attribute names a class derived from `ActionGroup`, then any static `` declarations in that group throw an exception. +> **WARNING** If a`` element's `class` attribute names a class derived from `ActionGroup`, then any static `` declarations in that group throw an exception. For a statically defined group, use `DefaultActionGroup`. ### Adding Child Actions to the Dynamic Group -To add actions to the `DynamicActionGroup`, a non-empty array of `AnAction` instances should be returned from the `DynamicActionGroup.getChildren()` method. +To add actions to the `DynamicActionGroup`, a non-empty array of `AnAction` instances should be returned from the `DynamicActionGroup.getChildren()` method. Here again, reuse the `PopupDialogAction` implementation. This use case is why `PopupDialogAction` overrides a constructor: @@ -214,6 +213,6 @@ public class DynamicActionGroup extends ActionGroup { } ``` -After providing the implementation of `DynamicActionGroup` and making it return a non-empty array of actions, the third position in the **Tools** Menu will contain a new group of actions: +After providing the implementation of `DynamicActionGroup` and making it return a non-empty array of actions, the third position in the **Tools** menu will contain a new group of actions: ![Dynamic Action Group](img/dynamic_action_group.png){:width="600px"} diff --git a/tutorials/action_system/working_with_custom_actions.md b/tutorials/action_system/working_with_custom_actions.md index 5b7846e6a..12c3c665d 100644 --- a/tutorials/action_system/working_with_custom_actions.md +++ b/tutorials/action_system/working_with_custom_actions.md @@ -4,18 +4,18 @@ title: Creating Actions ## Introduction -Plugins can add actions to existing IDE menus and toolbars, as well as add new menus and toolbars. -The IntelliJ Platform calls the actions of plugins in response to user interactions with the IDE. -However, the actions of a plugin must first be defined and registered with the IntelliJ Platform. +Plugins can add actions to existing IDE menus and toolbars, as well as add new menus and toolbars. +The IntelliJ Platform calls the actions of plugins in response to user interactions with the IDE. +However, the actions of a plugin must first be defined and registered with the IntelliJ Platform. -Using the SDK code sample `action_basics`, this tutorial illustrates the steps to create an action for a plugin. +Using the SDK code sample `action_basics`, this tutorial illustrates the steps to create an action for a plugin. * bullet list {:toc} ## Creating a Custom Action -Custom actions extend the abstract class [`AnAction`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java). -Classes that extend it should override `AnAction.update()`, and must override `AnAction.actionPerformed()`. +Custom actions extend the abstract class [`AnAction`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java). +Classes that extend it should override `AnAction.update()`, and must override `AnAction.actionPerformed()`. * The `update()` method implements the code that enables or disables an action. * The `actionPerformed()` method implements the code that executes when an action is invoked by the user. @@ -23,22 +23,23 @@ As an example, [`PopupDialogAction`](https://github.com/JetBrains/intellij-sdk-c ```java public class PopupDialogAction extends AnAction { - + @Override public void update(AnActionEvent e) { // Using the event, evaluate the context, and enable or disable the action. } - + @Override public void actionPerformed(@NotNull AnActionEvent e) { // Using the event, implement an action. For example, create and show a dialog. } - + } ``` -> **WARNING** `AnAction` classes do not have class fields of any kind. This restriction prevents memory leaks. -For more information about why, see [Action Implementation](/basics/action_system.md#action-implementation). +> **WARNING** `AnAction` classes do not have class fields of any kind. +> This restriction prevents memory leaks. +> For more information about why, see [Action Implementation](/basics/action_system.md#action-implementation). At this stage, `update()` implicitly defaults always to enable this action. The implementation of `actionPerformed()` does nothing. @@ -47,19 +48,19 @@ These methods fully implemented in [Developing the AnAction Methods](#developing Before fleshing out those methods, to complete this minimal implementation, `PopupDialogAction` must be registered with the IntelliJ Platform. ## Registering a Custom Action -Actions are registered by declaring them in code or by declaring them in the `` section of a plugin configuration (`plugin.xml`) file. +Actions are registered by declaring them in code or by declaring them in the `` section of a plugin configuration (`plugin.xml`) file. This section describes using IDE tooling - the New Action Form - to add a declaration to the `plugin.xml` file, and then tuning registration attributes manually. A more comprehensive explanation of action registration is available in the [Action Registration](/basics/action_system.md#registering-actions) section of this guide. ### Registering an Action with the New Action Form -IntelliJ IDEA has an embedded inspection that spots unregistered actions. -Verify the inspection is enabled at **Settings/Preferences \| Editor \| Inspections \| Plugin DevKit \| Code \| Component/Action not registered**. +IntelliJ IDEA has an embedded inspection that spots unregistered actions. +Verify the inspection is enabled at **Settings/Preferences \| Editor \| Inspections \| Plugin DevKit \| Code \| Component/Action not registered**. Here is an example for this stage of the `PopupDialogAction` class: !["Action never used" inspection](img/action_never_used.png){:width="600px"} To register `PopupDialogAction` and set up its basic attributes press ***Alt + Shift + Enter***. -Fill out the **New Action** form to set up the parameters for `PopupDialogAction`: +Fill out the **New Action** form to set up the parameters for `PopupDialogAction`: ![New Action](img/new_action.png){:width="800px"} @@ -72,17 +73,16 @@ The fields of the form are: * _Name_ - The text to appear in the menu. * _Description_ - Hint text to be displayed. * _Add to Group_ - The action group - menu or toolbar - to which the action is added. - Clicking in the list of groups and typing invokes a search, such as "ToolsMenu." -* _Anchor_ - Where the menu action should be placed in the **Tools** menu relative to the other actions in that menu. + Clicking in the list of groups and typing invokes a search, such as "ToolsMenu." +* _Anchor_ - Where the menu action should be placed in the **Tools** menu relative to the other actions in that menu. In this case, `PopupDialogAction` would be available in the **Tools** menu, it would be placed at the top, and would have no shortcuts. -After finishing the **New Action** form and applying the changes, the `` section of the plugin's `plugins.xml` file -would contain: +After finishing the **New Action** form and applying the changes, the `` section of the plugin's `plugins.xml` file would contain: ```xml - @@ -90,7 +90,7 @@ would contain: ``` The `` element declares the _Action ID_ (`id`,) _Class Name_ (`class`,) _Name_ (`text`,) and _Description_ from the **New Action** form. -The `` element declares where the action will appear and mirrors the names of entries from the form. +The `` element declares where the action will appear and mirrors the names of entries from the form. This declaration is adequate, but adding more attributes is discussed in the next section. @@ -142,15 +142,15 @@ The `update()` method defaults to always enable the action, which is satisfactor So `actionPerformed()` will be developed first. ### Extending the `actionPerformed()` Method -Adding code to the `PopupDialogAction.actionPerformed()` method makes the action do something useful. +Adding code to the `PopupDialogAction.actionPerformed()` method makes the action do something useful. The code below gets information from the `anActionEvent` input parameter and constructs a message dialog. A generic icon, and the `dlgMsg` and `dlgTitle` attributes from the invoking menu action are displayed. However, code in this method could manipulate a project, invoke an inspection, change the contents of a file, etc. -For demonstration purposes the `AnActionEvent.getData()` method tests if a [`Navigatable`](upsource:///platform/core-api/src/com/intellij/pom/Navigatable.java) object is available. -If so, information about the selected element is added to the dialog. +For demonstration purposes the `AnActionEvent.getData()` method tests if a [`Navigatable`](upsource:///platform/core-api/src/com/intellij/pom/Navigatable.java) object is available. +If so, information about the selected element is added to the dialog. -See [Determining the Action Context](/basics/action_system.md#determining-the-action-context) for more information about accessing information from the `AnActionEvent` input parameter. +See [Determining the Action Context](/basics/action_system.md#determining-the-action-context) for more information about accessing information from the `AnActionEvent` input parameter. ```java @Override @@ -170,11 +170,12 @@ See [Determining the Action Context](/basics/action_system.md#determining-the-ac ### Extending the `update()` Method Adding code to `PopupDialogAction.update()` gives finer control of the action's visibility and availability. -The action's state and(or) presentation can be dynamically changed depending on the context. +The action's state and(or) presentation can be dynamically changed depending on the context. -> **WARNING** This method needs to _execute very quickly_. For more information about this constraint, see the warning in [Overriding the AnAction.update Method](/basics/action_system.md#overriding-the-anactionupdate-method). +> **WARNING** This method needs to _execute very quickly_. +> For more information about this constraint, see the warning in [Overriding the AnAction.update Method](/basics/action_system.md#overriding-the-anactionupdate-method). -In this example, the `update()` method relies on a `Project` object being available. +In this example, the `update()` method relies on a `Project` object being available. This requirement means the user must have at least one project open in the IDE for the `PopupDialogAction` to be available. So the `update()` method disables the action for contexts where a `Project` object isn't defined. @@ -190,9 +191,9 @@ Setting both the enabled state and visibility produces consistent behavior despi } ``` -The `update()` method does not check to see if a `Navigatable` object is available before enabling `PopupDialogAction`. -This check is unnecessary because using the `Navigatable` object is opportunistic in `actionPerformed()`. -See [Determining the Action Context](/basics/action_system.md#determining-the-action-context) for more information about accessing information from the `AnActionEvent` input parameter. +The `update()` method does not check to see if a `Navigatable` object is available before enabling `PopupDialogAction`. +This check is unnecessary because using the `Navigatable` object is opportunistic in `actionPerformed()`. +See [Determining the Action Context](/basics/action_system.md#determining-the-action-context) for more information about accessing information from the `AnActionEvent` input parameter. ### Other Method Overrides A constructor is overridden in `PopupDialogAction`, but this is an artifact of reusing this class for a dynamically created menu action. diff --git a/tutorials/build_system.md b/tutorials/build_system.md index 0b204e43e..946cd847b 100644 --- a/tutorials/build_system.md +++ b/tutorials/build_system.md @@ -13,7 +13,7 @@ The plugin takes care of the dependencies of your plugin project - both the base The gradle-intellij-plugin provides tasks to run the IDE with your plugin and to publish your plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com). To make sure that your plugin is not affected by [API changes](/reference_guide/api_changes_list.md), which may happen between major releases of the platform, you can quickly build your plugin against many versions of the base IDE. -> **WARNING** When adding additional repositories to your Gradle build script, make sure always to use HTTPS protocol. +> **WARNING** When adding additional repositories to your Gradle build script, always use HTTPS protocol. > **NOTE** Please make sure to always upgrade to the latest version of `gradle-intellij-plugin`. Follow releases on [GitHub](https://github.com/JetBrains/gradle-intellij-plugin/releases). diff --git a/tutorials/build_system/deployment.md b/tutorials/build_system/deployment.md index daefb300f..10ec56d1b 100644 --- a/tutorials/build_system/deployment.md +++ b/tutorials/build_system/deployment.md @@ -3,25 +3,25 @@ title: Publishing Plugins with Gradle --- -Once you have configured Gradle support, you can automatically build and deploy your plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com). -To automatically deploy a plugin, you need to have _already published the plugin to the plugin repository at least once._ +Once you have configured Gradle support, you can automatically build and deploy your plugin to the [JetBrains Plugins Repository](https://plugins.jetbrains.com). +To automatically deploy a plugin, you need to have _already published the plugin to the plugin repository at least once._ Please see the guide page for manually [publishing a plugin](../../basics/getting_started/publishing_plugin.md) for the first time. > **TIP** Please see [Marketing](/appendix/resources/marketing.md) for remarks on how to prepare your plugin for optimal presentation. -> **WARNING** When adding additional repositories to your Gradle build script, make sure always to use HTTPS protocol. +> **WARNING** When adding additional repositories to your Gradle build script, always use HTTPS protocol. * bullet list {:toc} ## Building Distribution -For manual distribution or local installation, invoke `buildPlugin` Gradle task to create the plugin distribution. +For manual distribution or local installation, invoke the `buildPlugin` Gradle task to create the plugin distribution. The resulting JAR/ZIP is located in `build/distributions` and can then be [installed](https://www.jetbrains.com/help/idea/managing-plugins.html#installing-plugins-from-disk) either manually or uploaded to a [custom plugin repository](/basics/getting_started/update_plugins_format.md). ## Providing Your Hub Permanent Token to Gradle -To deploy a plugin to the JetBrains Plugins Repository, you need to supply your [JetBrains Hub Permanent Token](https://plugins.jetbrains.com/docs/marketplace/plugin-upload.html). +To deploy a plugin to the JetBrains Plugins Repository, you need to supply your [JetBrains Hub Permanent Token](https://plugins.jetbrains.com/docs/marketplace/plugin-upload.html). -This section describes two options to supply your _Hub Permanent Token_ via Gradle using: +This section describes two options to supply your _Hub Permanent Token_ via Gradle using: * Environment variables, * Parameters to the Gradle task. @@ -32,11 +32,11 @@ Start by defining an environment variable such as: export ORG_GRADLE_PROJECT_intellijPublishToken='YOUR_HUB_TOKEN_HERE' ``` -> **NOTE** On macOS systems, environment variables set in `.bash_profile` are only visible to processes you run from bash. +> **NOTE** On macOS systems, environment variables set in `.bash_profile` are only visible to processes you run from bash. Environment variables visible to all processes need to be defined in [Environment.plist](https://developer.apple.com/library/archive/qa/qa1067/_index.html). -Now provide the environment variable in the run configuration with which you run the `publishPlugin` task locally. -To do so, create a Gradle run configuration (if not already done), choose your Gradle project, specify the `publishPlugin` task, and then add the environment variable. +Now provide the environment variable in the run configuration with which you run the `publishPlugin` task locally. +To do so, create a Gradle run configuration (if not already done), choose your Gradle project, specify the `publishPlugin` task, and then add the environment variable. ```groovy publishPlugin { @@ -47,26 +47,26 @@ publishPlugin { Note that you still need to put some default values (can be empty) in the Gradle properties because otherwise, you will get a compilation error. ### Using Parameters for the Gradle Task -Similar to using environment variables, you can also pass your token as a parameter to the Gradle task. -For example, you can to provide the parameter `-Dorg.gradle.project.intellijPublishToken=YOUR_HUB_TOKEN_HERE` on the command line or by putting it in the arguments of your Gradle run configuration. +Like using environment variables, you can also pass your token as a parameter to the Gradle task. +For example, you can provide the parameter `-Dorg.gradle.project.intellijPublishToken=YOUR_HUB_TOKEN_HERE` on the command line or by putting it in the arguments of your Gradle run configuration. Note that also, in this case, you still need to put some default values in your Gradle properties. ## Deploying a Plugin with Gradle -The first step when deploying a plugin is to confirm that it works correctly. -You may wish to verify this by [installing your plugin from disk](https://www.jetbrains.com/help/idea/managing-plugins.html) on a fresh instance of your target IDE(s). +The first step when deploying a plugin is to confirm that it works correctly. +You may wish to verify this by [installing your plugin from disk](https://www.jetbrains.com/help/idea/managing-plugins.html) on a fresh instance of your target IDE(s). ### Publishing a Plugin -Once you are confident, the plugin works as intended, make sure the plugin version is updated, as the JetBrains Plugins Repository won't accept multiple artifacts with the same version. +Once you are confident, the plugin works as intended, make sure the plugin version is updated, as the JetBrains Plugins Repository won't accept multiple artifacts with the same version. -To deploy a new version of your plugin to the JetBrains Plugins Repository, invoke `publishPlugin` Gradle task. +To deploy a new version of your plugin to the JetBrains Plugins Repository, invoke the `publishPlugin` Gradle task. -Now check the most recent version of your plugin that appears on the [JetBrains Plugins Repository](https://plugins.jetbrains.com/). +Now check the most recent version of your plugin on the [JetBrains Plugins Repository](https://plugins.jetbrains.com/). If successfully deployed, any users who currently have your plugin installed on an available version of the IntelliJ Platform are notified of a new update available as soon as the update has been verified. ### Specifying a Release Channel -You may also deploy plugins to a release channel of your choosing, by configuring the `publishPlugin.channels` property. +You may also deploy plugins to a release channel of your choosing, by configuring the `publishPlugin.channels` property. For example: ```groovy @@ -75,16 +75,16 @@ publishPlugin { } ``` -When empty, this uses the default plugin repository, available to all [JetBrains Plugins Repository](https://plugins.jetbrains.com/) users. -However, you can publish it to an arbitrarily-named channel. -These non-default release channels are treated as separate repositories. +When empty, this uses the default plugin repository, available to all [JetBrains Plugins Repository](https://plugins.jetbrains.com/) users. +However, you can publish it to an arbitrarily-named channel. +These non-default release channels are treated as separate repositories. -When using a non-default release channel, users need to configure a new [custom plugin repository](https://www.jetbrains.com/help/idea/managing-plugins.html#repos) in their IDE to install your plugin. -For example, if you specify `publishPlugin.channels 'canary'`, then users need to add the `https://plugins.jetbrains.com/plugins/canary/list` repository to install the plugin and receive updates. +When using a non-default release channel, users need to configure a new [custom plugin repository](https://www.jetbrains.com/help/idea/managing-plugins.html#repos) in their IDE to install your plugin. +For example, if you specify `publishPlugin.channels 'canary'`, then users need to add the `https://plugins.jetbrains.com/plugins/canary/list` repository to install the plugin and receive updates. Popular channel names include: * `alpha`: https://plugins.jetbrains.com/plugins/alpha/list * `beta`: https://plugins.jetbrains.com/plugins/beta/list * `eap`: https://plugins.jetbrains.com/plugins/eap/list -More information about the available configuration options is in the [documentation of the intellij gradle plugin](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#publishing-dsl). +More information about the available configuration options is in the [documentation of the IntelliJ Gradle plugin](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md#publishing-dsl). diff --git a/tutorials/build_system/gradle_guide.md b/tutorials/build_system/gradle_guide.md index 2571d8c0e..b5bc4e1d6 100644 --- a/tutorials/build_system/gradle_guide.md +++ b/tutorials/build_system/gradle_guide.md @@ -4,21 +4,21 @@ title: Configuring Gradle Projects This page serves as a guide to the Gradle-based plugin configuration for _IntelliJ Platform_ projects. -The IntelliJ IDEA Ultimate and Community editions bundle the _Gradle_ and _Plugin DevKit_ plugins to support Gradle-based development. +The IntelliJ IDEA Ultimate and Community editions bundle the _Gradle_ and _Plugin DevKit_ plugins to support Gradle-based development. The [Getting Started with Gradle](prerequisites.md) page provides a tutorial for creating Gradle-based IntelliJ Platform plugins. It may be useful to review the IntelliJ Platform page, particularly the description of versioning in the [Open Source](/intro/intellij_platform.md#open-source) section. -> **WARNING** When adding additional repositories to your Gradle build script, make sure always to use HTTPS protocol. +> **WARNING** When adding additional repositories to your Gradle build script, always use HTTPS protocol. * bullet list {:toc} -## Overview of the Gradle Plugin +## Overview of the Gradle Plugin The Gradle plugin is built from the open-source project [gradle-intellij-plugin](https://github.com/JetBrains/gradle-intellij-plugin). This plugin adds Gradle tasks that enable developing IntelliJ Platform plugins. The [README](https://github.com/JetBrains/gradle-intellij-plugin/blob/master/README.md) file has a reference for configuring these tasks. - + When getting started, there are several items to note on the README page: * At the top of the page, the [latest production version](https://github.com/JetBrains/gradle-intellij-plugin#the-latest-version) of the plugin is listed. It is advised to upgrade to the latest available version regularly. * Also, at the top is the minimum required version of Gradle. @@ -38,14 +38,14 @@ This section presents a guided tour of Gradle plugin attributes to achieve the c ### Configuring the Gradle Plugin for Building IntelliJ Platform Plugin Projects By default, the Gradle plugin will build a plugin project against the IntelliJ Platform defined by the latest EAP snapshot of the IntelliJ IDEA Community Edition. -> **NOTE** Using EAP versions of the IntelliJ Platform requires adding the _Snapshots repository_ to the `build.gradle` file (see [IntelliJ Platform Artifacts Repositories](/reference_guide/intellij_artifacts.md)). +> **NOTE** Using EAP versions of the IntelliJ Platform requires adding the _Snapshots repository_ to the `build.gradle` file (see [IntelliJ Platform Artifacts Repositories](/reference_guide/intellij_artifacts.md)). If a matching version of the specified IntelliJ Platform is not available on the local machine, the Gradle plugin downloads the correct version and type. IntelliJ IDEA then indexes the build and any associated source code and JetBrains Java Runtime. #### IntelliJ Platform Configuration Explicitly setting the [Setup DSL](https://github.com/JetBrains/gradle-intellij-plugin#setup-dsl) attributes `intellij.version` and `intellij.type` tells the Gradle plugin to use that configuration of the IntelliJ Platform to create the plugin project. - + All available platform versions can be browsed in the [IntelliJ Platform Artifacts Repositories](/reference_guide/intellij_artifacts.md). If the chosen platform version is not available in the repositories, or a local installation of the target IDE is the desired type and version of the IntelliJ Platform, use `intellij.localPath` to point to that installation. @@ -78,7 +78,7 @@ The Gradle plugin will fetch the specified JetBrains Runtime as needed. There are several attributes to control where the Gradle plugin places directories for downloads and use by the IDE Development Instance. The location of the [sandbox home](/basics/ide_development_instance.md#sandbox-home-location-for-gradle-based-plugin-projects) directory and its subdirectories can be controlled with Gradle plugin attributes. -The `intellij.sandboxDirectory` attribute is used to set the path for the sandbox directory to be used while running the plugin in an IDE Development Instance. +The `intellij.sandboxDirectory` attribute is used to set the path for the sandbox directory to be used while running the plugin in an IDE Development Instance. Locations of the sandbox [subdirectories](/basics/ide_development_instance.md#development-instance-settings-caches-logs-and-plugins) can be controlled using the `runIde.configDirectory`, `runIde.pluginsDirectory`, and `runIde.systemDirectory` attributes. If the `intellij.sandboxDirectory` path is explicitly set, the subdirectory attributes default to the new sandbox directory. @@ -94,17 +94,17 @@ The plugin version is defined in the `plugins {}` section of a project's `build. The version of the Gradle is defined in `/gradle/wrapper/gradle-wrapper.properties`. ### Patching the Plugin Configuration File -A plugin project's `plugin.xml` file has element values that are "patched" at build time from the attributes of the `patchPluginXml` task ([Patching DSL](https://github.com/JetBrains/gradle-intellij-plugin#patching-dsl)). +A plugin project's `plugin.xml` file has element values that are "patched" at build time from the attributes of the `patchPluginXml` task ([Patching DSL](https://github.com/JetBrains/gradle-intellij-plugin#patching-dsl)). As many as possible of the attributes in the Patching DSL will be substituted into the corresponding element values in a plugin project's `plugin.xml` file: * If a `patchPluginXml` attribute default value is defined, the attribute value will be patched in `plugin.xml` _regardless of whether the `patchPluginXml` task appears in the `build.gradle` file_. * For example, the default values for the attributes `patchPluginXml.sinceBuild` and `patchPluginXml.untilBuild` are defined based on the declared (or default) value of `intellij.version`. So by default `patchPluginXml.sinceBuild` and `patchPluginXml.untilBuild` are substituted into the `` element's `since-build` and `until-build` attributes in the `plugin.xml` file. * If a `patchPluginXml` attribute value is explicitly defined, the attribute value will be substituted in `plugin.xml`. - * If both `patchPluginXml.sinceBuild` and `patchPluginXml.untilBuild` attributes are explicitly set, both are substituted in `plugin.xml`. + * If both `patchPluginXml.sinceBuild` and `patchPluginXml.untilBuild` attributes are explicitly set, both are substituted in `plugin.xml`. * If one attribute is explicitly set (e.g. `patchPluginXml.sinceBuild`) and one is not (e.g. `patchPluginXml.untilBuild` has a default value,) both attributes are patched at their respective (explicit and default) values. * For **no substitution** of the `` element's `since-build` and `until-build` attributes, one of the following must appear in the `build.gradle` file: * Either set `intellij.updateSinceUntilBuild = false`, which will disable substituting both `since-build` and `until-build` attributes, - * Or, for independent control, set `patchPluginXml.sinceBuild(null)` and `patchPluginXml.untilBuild(null)` depending on whether the intention is to disable one or both substitutions. + * Or, for independent control, set `patchPluginXml.sinceBuild(null)` and `patchPluginXml.untilBuild(null)` depending on whether the intention is to disable one or both substitutions. A best practice to avoid confusion is to replace the elements in `plugin.xml` the Gradle plugin will patch that with a comment. That way, the values for these parameters do not appear in two places in the source code. @@ -116,8 +116,8 @@ For those `patchPluginXml` attributes that contain descriptions such as `changeN As discussed in [Components of a Wizard-Generated Gradle IntelliJ Platform Plugin](prerequisites.md#components-of-a-wizard-generated-gradle-intellij-platform-plugin), the Gradle properties `project.version`, `project.group`, and `rootProject.name` are all generated based on the input to the Wizard. However, the `gradle-intellij-plugin` does not combine and substitute those Gradle properties for the default `` and `` elements in the `plugin.xml` file. -The best practice is to keep `project.version` current. -By default, if you modify `project.version` in `build.gradle`, the Gradle plugin will automatically update the `` value in the `plugin.xml` file. +The best practice is to keep `project.version` current. +By default, if you modify `project.version` in `build.gradle`, the Gradle plugin will automatically update the `` value in the `plugin.xml` file. This practice keeps all version declarations synchronized. ### Publishing with the Gradle Plugin @@ -132,13 +132,13 @@ This section reviews some of the more common configurations. ### Plugins Targeting IntelliJ IDEA IntelliJ Platform plugins targeting IntelliJ IDEA have the most straightforward Gradle plugin configuration. * Determine the version of [IntelliJ IDEA to use for building the plugin project](#configuring-the-gradle-plugin-for-building-intellij-platform-plugin-projects); this is the desired version of the IntelliJ Platform. - This can be EAP (default) or determined from the [build number ranges](/basics/getting_started/build_number_ranges.md). - * If a production version of IntelliJ IDEA is the desired target, set the `intellij` [version attributes](#intellij-platform-configuration) accordingly. - * Set the necessary [plugin dependencies](#plugin-dependencies), if any. -* If the plugin project should be run or debugged in an IDE Development Instance based on the same IntelliJ IDEA version, no further attributes need to be set for the IDE Development Instance. - This is the default behavior and is the most common use case. + This can be EAP (default) or determined from the [build number ranges](/basics/getting_started/build_number_ranges.md). + * If a production version of IntelliJ IDEA is the desired target, set the `intellij` [version attributes](#intellij-platform-configuration) accordingly. + * Set the necessary [plugin dependencies](#plugin-dependencies), if any. +* If the plugin project should be run or debugged in an IDE Development Instance based on the same IntelliJ IDEA version, no further attributes need to be set for the IDE Development Instance. + This is the default behavior and is the most common use case. * If the plugin project should be run or debugged in an IDE Development Instance based on an alternate version of the IntelliJ Platform, set the [Running](#running-against-alternate-versions-and-types-of-intellij-platform-based-ides) DSL attribute accordingly. - * If the plugin project should be run using a JetBrains Runtime other than the default for the IDE Development Instance, specify the [JetBrains Runtime version](#running-against-alternate-versions-of-the-jetbrains-runtime). + * If the plugin project should be run using a JetBrains Runtime other than the default for the IDE Development Instance, specify the [JetBrains Runtime version](#running-against-alternate-versions-of-the-jetbrains-runtime). * Set the appropriate attributes for [patching the `plugin.xml` file](#patching-the-plugin-configuration-file). ### Plugins Targeting Alternate IntelliJ Platform-Based IDEs diff --git a/tutorials/build_system/prerequisites.md b/tutorials/build_system/prerequisites.md index 114f39e79..b99abe1c5 100644 --- a/tutorials/build_system/prerequisites.md +++ b/tutorials/build_system/prerequisites.md @@ -10,8 +10,7 @@ To verify these plugins are installed and enabled, see the help section about [M > **TIP** [IntelliJ Platform Plugin Template](https://github.com/JetBrains/intellij-platform-plugin-template) makes it easier to create and maintain your IDE plugins, having the Gradle plugin already integrated and CI covered with GitHub Actions. -> **WARNING** When adding additional repositories to your Gradle build script, make sure always to use HTTPS protocol. - +> **WARNING** When adding additional repositories to your Gradle build script, always use HTTPS protocol. * bullet list {:toc} @@ -30,15 +29,16 @@ It guides you through the Gradle project creation process with two screens. ### New Project Configuration Screen On the first screen, the type of project is configured: * From the _project type_ pane on the left, choose _Gradle_. -* Specify the _Project SDK_ based on the **Java 8** JDK. +* Specify the _Project SDK_ based on the **Java 8** JDK. This SDK will be the default JRE used to run Gradle, and the JDK version used to compile the plugin Java sources. * In the _Additional Libraries and Frameworks_ panel, select _Java_ and _IntelliJ Platform Plugin_. These settings will be used for the remainder of this tutorial. Optionally: - * To include support for the Kotlin language in the plugin, check the _Kotlin/JVM_ box (circled in green below). - This option can be selected with or without the _Java_ language. See [Kotlin for Plugin Developers](/tutorials/kotlin.md) for more information. - * To create the `build.gradle` file as a Kotlin build script (`build.gradle.kts`) rather than Groovy, check the _Kotlin DSL build script_ box (circled in magenta below). +* To include support for the Kotlin language in the plugin, check the _Kotlin/JVM_ box (circled in green below). + This option can be selected with or without the _Java_ language. + See [Kotlin for Plugin Developers](/tutorials/kotlin.md) for more information. +* To create the `build.gradle` file as a Kotlin build script (`build.gradle.kts`) rather than Groovy, check the _Kotlin DSL build script_ box (circled in magenta below). Then click _Next_: @@ -51,12 +51,12 @@ Expand the _Artifact Coordinates_ section and specify a [GroupId, ArtifactId, an * _ArtifactId_ is the default name of the project JAR file (without version). It is also used for the Gradle property `rootProject.name` value in the project's `settings.gradle` file. For this example, enter `my_gradle_plugin`. -* _Version_ is used for the Gradle property `project.version` value in the `build.gradle` file. +* _Version_ is used for the Gradle property `project.version` value in the `build.gradle` file. For this example, enter `1.0`. The _Name_ field is synced automatically with the specified _ArtifactId_. -Specify the path for the new project in _Location_ and click _Finish_ to continue and generate the project. +Specify the path for the new project in _Location_ and click _Finish_ to continue and generate the project. ### Components of a Wizard-Generated Gradle IntelliJ Platform Plugin @@ -66,18 +66,18 @@ For the [example](#creating-a-gradle-based-intellij-platform-plugin-with-new-pro my_gradle_plugin ├── build.gradle ├── gradle -│   └── wrapper -│   ├── gradle-wrapper.jar -│   └── gradle-wrapper.properties +│ └── wrapper +│ ├── gradle-wrapper.jar +│ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main - │   ├── java - │   └── resources - │   └── META-INF - │   └── plugin.xml + │ ├── java + │ └── resources + │ └── META-INF + │ └── plugin.xml └── test ├── java └── resources @@ -97,18 +97,18 @@ The generated `my_gradle_plugin` project `build.gradle` file: id 'java' id 'org.jetbrains.intellij' version '0.4.22' } - + group 'com.your.company' - version '1.0' + version '1.0' sourceCompatibility = 1.8 - + repositories { mavenCentral() - } + } dependencies { testImplementation group: 'junit', name: 'junit', version: '4.12' } - + // See https://github.com/JetBrains/gradle-intellij-plugin/ intellij { version '2020.1' @@ -143,19 +143,19 @@ The `` value must be a unique identifier over all plugins, typically a conca Please note that it is impossible to change the `` of a published plugin without losing automatic updates for existing installations. ## Adding Gradle Support to an Existing DevKit-Based IntelliJ Platform Plugin -Converting a [DevKit-based](/basics/getting_started/using_dev_kit.md) plugin project to a Gradle-based plugin project can be done using the New Project Wizard to create a Gradle-based project around the existing DevKit-based project: +Converting a [DevKit-based](/basics/getting_started/using_dev_kit.md) plugin project to a Gradle-based plugin project can be done using the New Project Wizard to create a Gradle-based project around the existing DevKit-based project: * Ensure the directory containing the DevKit-based IntelliJ Platform plugin project can be fully recovered if necessary. * Delete all the artifacts of the DevKit-based project: * `.idea` directory * `[modulename].iml` file * `out` directory -* Arrange the existing source files within the project directory in the Gradle [SourceSet](https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_project_layout) format. +* Arrange the existing source files within the project directory in the Gradle [SourceSet](https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_project_layout) format. * Use the New Project Wizard as though creating a [new Gradle project](#creating-a-gradle-based-intellij-platform-plugin-with-new-project-wizard) from scratch. * On the [Project Naming/Artifact Coordinates Screen](#project-namingartifact-coordinates-screen) set the values to: * _GroupId_ to the existing package in the initial source set. * _ArtifactId_ to the name of the existing plugin. * _Version_ to the same as the existing plugin. - * _Name_ to the name of the existing plugin. + * _Name_ to the name of the existing plugin. (It should be pre-filled from the _ArtifactId_) * Set the _Location_ to the directory of the existing plugin. * Click _Finish_ to create the new Gradle-based plugin. @@ -167,16 +167,16 @@ Gradle projects are run from the IDE's Gradle Tool window. ### Adding Code to the Project Before running [`my_gradle_project`](#components-of-a-wizard-generated-gradle-intellij-platform-plugin), some code can be added 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. -### Executing the Plugin -Open the Gradle tool window and search for the `runIde` task: -* If it’s not in the list, hit the [Refresh](https://www.jetbrains.com/help/idea/jetgradle-tool-window.html#1eeec055) button at the top of the Gradle window. +### Executing the Plugin +Open the Gradle tool window and search for the `runIde` task: +* If it’s not in the list, hit the [Refresh](https://www.jetbrains.com/help/idea/jetgradle-tool-window.html#1eeec055) button at the top of the Gradle window. * Or [Create a new Gradle Run Configuration](https://www.jetbrains.com/help/idea/create-run-debug-configuration-gradle-tasks.html). - + ![Gradle Tool Window](img/gradle_tasks_in_tool_window.png){:width="398px"} - + Double-click on the _runIde_ task to execute it. See the IntelliJ IDEA help for more information about [Working with Gradle tasks](https://www.jetbrains.com/help/idea/gradle.html#96bba6c3). -Finally, when `my_gradle_plugin` launches in the IDE development instance, there should be a new menu under the **Tools** menu. +Finally, when `my_gradle_plugin` launches in the IDE development instance, there should be a new menu under the **Tools** menu. diff --git a/tutorials/code_inspections.md b/tutorials/code_inspections.md index 34994e918..e51c6df8c 100644 --- a/tutorials/code_inspections.md +++ b/tutorials/code_inspections.md @@ -9,14 +9,14 @@ Examples of the plugin approach are the IntelliJ Platform SDK code samples [insp In addition, the comparing_references_inspection code sample demonstrates implementing a unit test. You can also create custom inspections through the IntelliJ IDEA user interface. -See [Code Inspection](https://www.jetbrains.com/idea/webhelp/code-inspection.html) and [Creating Custom Inspections](https://www.jetbrains.com/idea/help/creating-custom-inspections.html) for more information. +See [Code Inspection](https://www.jetbrains.com/idea/webhelp/code-inspection.html) and [Creating Custom Inspections](https://www.jetbrains.com/idea/help/creating-custom-inspections.html) for more information. ## Creating an Inspection Plugin The [comparing_references_inspection](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/comparing_references_inspection) code sample adds a new inspection to the **Java | Probable Bugs** group in the [Inspections list](https://www.jetbrains.com/help/idea/inspections-settings.html). -The inspection reports when the `==` or `!=` operator is used between Java expressions of reference types. +The inspection reports when the `==` or `!=` operator is used between Java expressions of reference types. It illustrates the components for a custom inspection plugin: -* Describing an [inspection](#plugin-configuration-file) in the plugin configuration file. +* Describing an [inspection](#plugin-configuration-file) in the plugin configuration file. * Implementing a [local inspection class](#inspection-implementation-java-class) to inspect Java code in the IntelliJ Platform-based IDE editor. * Creating a [visitor](#visitor-implementation-class) to traverse the `PsiTree` of the Java file being edited, inspecting for problematic syntax. * Implementing a [quick fix](#quick-fix-implementation) class to correct syntax problems by altering the `PsiTree` as needed. @@ -27,7 +27,7 @@ It illustrates the components for a custom inspection plugin: Although the IntelliJ Platform SDK code samples illustrate implementations of these components, it is often useful to see examples of inspections implemented in the _intellij_community_ code base. This process can help find inspection descriptions and implementations based on what is visible in the IDE UI. -The overall approach works for inspections aimed at other languages as well. +The overall approach works for inspections aimed at other languages as well. * Find an existing inspection that is similar to the one you want to implement in the **Preferences | Editor | Inspections** panel. Note the display name of the inspection. For example, the Java/Probable Bugs inspection "Object comparison using '==', instead of 'equals()'" is very similar to `comparing_references_inspection`. @@ -43,7 +43,7 @@ The overall approach works for inspections aimed at other languages as well. ## Creating an Inspection The [comparing_references_inspection](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/comparing_references_inspection) code sample reports when the `==` or `!=` operators are used between Java expressions of reference types. The user can apply a quick fix to change `a==b` to `a.equals(b)`, or `a!=b` to `!a.equals(b)`. - + The details of the `comparing_references_inspection` implementation illustrate the components of an inspection plugin. ### Plugin Configuration File @@ -54,13 +54,13 @@ Under the hood, inspection types are described as an `` in [`Lan * The `inspectionToolProvider` type is not deprecated but `localInspection` is preferred. The minimum inspection description must contain the `implementationClass` attribute. -As shown in the `comparing_references_inspection` plugin configuration file, other attributes can be defined in the `localInspection` element, either with or without localization. +As shown in the `comparing_references_inspection` plugin configuration file, other attributes can be defined in the `localInspection` element, either with or without localization. In most cases, it is simplest to define the attributes in the plugin configuration file because the underlying parent classes handle most of the class responsibilities based on the configuration file description. Note that some attributes are not displayed to the user, so they are never localized. As an alternative, inspections can define all of the attribute information (except `implementationClass`) by overriding methods in the inspection implementation class. -### Inspection Implementation Java Class +### Inspection Implementation Java Class Inspection implementations for Java files, like [`ComparingReferencesInspection`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/comparing_references_inspection/src/main/java/org/intellij/sdk/codeInspection/ComparingReferencesInspection.java), are often based on the Java class [`AbstractBaseJavaLocalInspectionTool`](upsource:///java/java-analysis-api/src/com/intellij/codeInspection/AbstractBaseJavaLocalInspectionTool.java). The `AbstractBaseJavaLocalInspectionTool` implementation class offers methods to inspect Java classes, fields, and methods. @@ -85,7 +85,7 @@ The overridden `ComparingReferencesInspection` methods are discussed in the sect The visitor class evaluates whether elements of the file's `PsiTree` are of interest to an inspection. The `ComparingReferencesInspection.buildVisitor()` method creates an anonymous visitor class based on [`JavaElementVisitor`](upsource:///java/java-psi-api/src/com/intellij/psi/JavaElementVisitor.java) to traverse the `PsiTree` of the Java file being edited, inspecting for suspect syntax. -The anonymous class overrides three methods in particular. +The anonymous class overrides three methods in particular. * `visitReferenceExpression()` to prevent any duplicate visitation of reference-type expressions. * `visitBinaryExpression()`, which does all the heavy lifting. It is called to evaluate a `PsiBinaryExpression`, and it checks to see if the operands are `==` or `!=`, and if the operands are classes relevant to this inspection. @@ -116,15 +116,15 @@ Note that the IntelliJ Platform provides most of the UI displayed in the _Inspec As long as the inspection attributes and inspection description are defined correctly, the IntelliJ Platform displays the information in the _Inspections Preferences_ UI. ### Inspection Description -The inspection description is an HTML file. +The inspection description is an HTML file. The description is displayed in the upper right panel of the _Inspections Preferences_ dialog when an inspection is selected from the list. - + Implicit in using [`LocalInspectionTool`](upsource:///platform/analysis-api/src/com/intellij/codeInspection/LocalInspectionTool.java) in the class hierarchy of the inspection implementation means following some conventions. * The inspection description file is expected to be located under `/resources/inspectionDescriptions/`. If the inspection description file is to be located elsewhere, override `getDescriptionUrl()` in the inspection implementation class. * The name of the description file is expected to be the inspection `.html` as provided by the inspection description or the inspection implementation class. If a short name is not provided by the plugin, the IntelliJ Platform computes one. - + ### Inspection Unit Test > **NOTE** Please note that running the test requires setting system property `idea.home.path` in `test {}` block of `build.gradle` @@ -144,7 +144,7 @@ The `comparing_references_inspection` tests run the inspection on the `*.java` f ## Running the Comparing References Inspection Code Sample The [comparing_references_inspection](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/comparing_references_inspection) code sample adds a new inspection to the **Java | Probable Bugs** group in the [Inspections list](https://www.jetbrains.com/help/idea/inspections-settings.html). -The inspection reports when the `==` or `!=` operator is used between Java expressions of reference types. +The inspection reports when the `==` or `!=` operator is used between Java expressions of reference types. To run the sample plugin: * Start **IntelliJ IDEA**, open the `intellij-sdk-docs` project, and highlight the [comparing_references_inspection](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/comparing_references_inspection) module. @@ -154,11 +154,11 @@ To run the sample plugin: ### Configuring the Plugin -Once the plugin is launched, you can set the plugin options. +Once the plugin is launched, you can set the plugin options. You can specify the Java classes to participate in the code inspection and the severity level of the found probable bugs. -On the IDEA main menu, open the **Preferences | Editor | Inspections** dialog. -In the list of the IntelliJ IDEA _Java_ inspections, expand the _Probable bugs_ node, and then click _SDK: '==' or '!=' instead of 'equals()'_. +On the IDEA main menu, open the **Preferences | Editor | Inspections** dialog. +In the list of the IntelliJ IDEA _Java_ inspections, expand the _Probable bugs_ node, and then click _SDK: '==' or '!=' instead of 'equals()'_. ![](img/comparingReferences_options.png) @@ -169,12 +169,12 @@ Under **Options**, you can specify the following plugin settings: ### How does it work? -The plugin inspects your code opened in the IntelliJ IDEA editor or the code you are typing. +The plugin inspects your code opened in the IntelliJ IDEA editor or the code you are typing. The plugin highlights the code fragments where two variables of the reference type are separated by `==` or `!=` and proposes to replace this code fragment with `.equals()`: ![](img/comparingReferences.png) -In this example, the `str1` and `str2` are variables of the String type. +In this example, the `str1` and `str2` are variables of the String type. Clicking _SDK: Use equals()_ replaces: ```java diff --git a/tutorials/code_intentions.md b/tutorials/code_intentions.md index f8d1fd307..173b1cc95 100644 --- a/tutorials/code_intentions.md +++ b/tutorials/code_intentions.md @@ -3,14 +3,14 @@ title: Code Intentions --- -This topic describes the [conditional_operator_intention](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/conditional_operator_intention), a sample plugin that adds a new [intention action](https://www.jetbrains.com/help/idea/intention-actions.html) to the IntelliJ Platform Intentions list. +This topic describes the [conditional_operator_intention](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/conditional_operator_intention), a sample plugin that adds a new [intention action](https://www.jetbrains.com/help/idea/intention-actions.html) to the IntelliJ Platform Intentions list. In addition, the sample plugin contains a JUnit-based test. ## About Intention Actions -The **IntelliJ Platform** analyzes your code and helps handle situations that may result in errors. -When a possible problem is suspected, the IDE suggests an appropriate intention action, denoted with special icons. -For more information, refer to [Intention Actions](https://www.jetbrains.com/help/idea/intention-actions.html) in the **IntelliJ IDEA** Web Help. +The **IntelliJ Platform** analyzes your code and helps handle situations that may result in errors. +When a possible problem is suspected, the IDE suggests an appropriate intention action, denoted with special icons. +For more information, refer to [Intention Actions](https://www.jetbrains.com/help/idea/intention-actions.html) in the **IntelliJ IDEA** Web Help. You can view a list of all available intention actions using the [Intention List](https://www.jetbrains.com/help/idea/intention-actions.html#intention-settings) provided by the IDE. @@ -18,7 +18,7 @@ You can view a list of all available intention actions using the [Intention List 1. Open the **Settings** dialog box. 2. Under **IDE Settings**, click **Intentions**. This displays the list of all intention actions currently available in **IntelliJ IDEA**. -- The intention actions are grouped according to the areas of their use. +- The intention actions are grouped according to the areas of their use. - To enable/disable an intention action, select/deselect the check box to its left. ## Techniques Used @@ -32,7 +32,7 @@ The [conditional_operator_intention](https://github.com/JetBrains/intellij-sdk-c ## Sample Plugin -The **ConditionalOperatorConverter** sample plugin is available in the `<%IntelliJ SDK Docs project%>/code_samples/conditional_operator_intention` directory. +The **ConditionalOperatorConverter** sample plugin is available in the `<%IntelliJ SDK Docs project%>/code_samples/conditional_operator_intention` directory. When launched, this plugin adds the **Convert ternary operator if statement** item to the **Conditional Operator** node in the IDEA Intentions list: ![](img/IntentionsList.png) @@ -47,7 +47,7 @@ When launched, this plugin adds the **Convert ternary operator if statement** it #### How does it work? -The plugin analyzes symbols under the cursor in your code opened in the IDEA editor. +The plugin analyzes symbols under the cursor in your code opened in the IDEA editor. If the cursor is positioned on the "?" conditional operator, **IntelliJ IDEA** proposes to replace this conditional (ternary) operator with the "if-then-else" statement: ![](img/TernaryOperator.png) @@ -71,7 +71,7 @@ if ((n>=0)) { ##### Testing the Plugin > **NOTE** Please note that running the test requires setting system property `idea.home.path` in `test {}` block of `build.gradle` -The sample plugin contains the `ConditionalOperatorConverterTest` Java class and the test data in the `test/testData/` directory. +The sample plugin contains the `ConditionalOperatorConverterTest` Java class and the test data in the `test/testData/` directory. To perform the plugin test, run the `ConditionalOperatorConverterTest.testIntention()` method. For detailed information about testing and all related procedures, refer to [Testing](https://www.jetbrains.com/help/idea/performing-tests.html) in the **IntelliJ IDEA** Web Help. diff --git a/tutorials/custom_language_support/annotator.md b/tutorials/custom_language_support/annotator.md index 3eea66674..3f01f84a7 100644 --- a/tutorials/custom_language_support/annotator.md +++ b/tutorials/custom_language_support/annotator.md @@ -6,10 +6,10 @@ title: 7. Annotator An `Annotator` helps highlight and annotate any code based on specific rules. This section adds annotation functionality to support the Simple Language in the context of Java code. -**Reference**: [Annotator](/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md#annotator) +**Reference**: [Annotator](/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md#annotator) * bullet list -{:toc} +{:toc} ## Required Project Configuration Changes Classes defined in this step of the tutorial depend on `com.intellij.psi.PsiLiteralExpression` at runtime. @@ -34,7 +34,7 @@ Consider a literal string that starts with "simple:" as a prefix of a Simple Lan It isn't part of the Simple Language, but it is a useful convention for detecting Simple Language keys embedded as string literals in other languages, like Java. Annotate the `simple:key` literal expression, and differentiate between a well-formed vs. an unresolved property. -> **NOTE** The use of new `AnnotationHolder` syntax starting 2020.2, which uses the builder format. +> **NOTE** The use of new `AnnotationHolder` syntax starting 2020.2, which uses the builder format. ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/SimpleAnnotator.java %} @@ -62,7 +62,7 @@ public class Test { } ``` -Open this Java file in an IDE Development Instance running the `simple_language_plugin` to check if the IDE resolves a property: +Open this Java file in an IDE Development Instance running the `simple_language_plugin` to check if the IDE resolves a property: ![Annotator](img/annotator.png){:width="800px"} @@ -70,4 +70,4 @@ If the property is an undefined name, the annotator flags the code with an error ![Unresolved property](img/unresolved_property.png){:width="800px"} -Try changing the Simple Language [color settings](/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md#run-the-project-1) to differentiate the annotation from the default language color settings. \ No newline at end of file +Try changing the Simple Language [color settings](/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md#run-the-project-1) to differentiate the annotation from the default language color settings. diff --git a/tutorials/custom_language_support/code_style_settings.md b/tutorials/custom_language_support/code_style_settings.md index 6e725bd48..3f6225d01 100644 --- a/tutorials/custom_language_support/code_style_settings.md +++ b/tutorials/custom_language_support/code_style_settings.md @@ -3,11 +3,11 @@ title: 16. Code Style Settings --- -Code style settings enable defining formatting options. -A code style settings provider creates an instance of the settings and also creates an options page in settings/preferences. +Code style settings enable defining formatting options. +A code style settings provider creates an instance of the settings and also creates an options page in settings/preferences. This example creates a settings/preferences page that uses the default language code style settings, customized by a language code style settings provider. -**Reference**: [Code Style Settings](/reference_guide/custom_language_support/code_formatting.md#code-style-settings) +**Reference**: [Code Style Settings](/reference_guide/custom_language_support/code_formatting.md#code-style-settings) * bullet list {:toc} @@ -20,7 +20,7 @@ Define a code style settings for Simple Language by subclassing [`CustomCodeStyl ``` ## 16.2. Define Code Style Settings Provider -The code style settings provider gives the IntelliJ Platform a standard way to instantiate `CustomCodeStyleSettings` for the Simple Language. +The code style settings provider gives the IntelliJ Platform a standard way to instantiate `CustomCodeStyleSettings` for the Simple Language. Define a code style settings provider for Simple Language by subclassing [`CodeStyleSettingsProvider`](upsource:///platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsProvider.java). ```java @@ -28,7 +28,7 @@ Define a code style settings provider for Simple Language by subclassing [`CodeS ``` ## 16.3. Register the Code Style Settings Provider -The `SimpleCodeStyleSettingsProvider` implementation is registered with the IntelliJ Platform in the plugin configuration file using the `com.intellij.codeStyleSettingsProvider` extension point. +The `SimpleCodeStyleSettingsProvider` implementation is registered with the IntelliJ Platform in the plugin configuration file using the `com.intellij.codeStyleSettingsProvider` extension point. ```xml @@ -44,11 +44,11 @@ Define a code style settings provider for Simple Language by subclassing [`Langu ``` ## 16.5. Register the Language Code Style Settings Provider -The `SimpleLanguageCodeStyleSettingsProvider` implementation is registered with the IntelliJ Platform in the plugin configuration file using the `com.intellij.langCodeStyleSettingsProvider` extension point. +The `SimpleLanguageCodeStyleSettingsProvider` implementation is registered with the IntelliJ Platform in the plugin configuration file using the `com.intellij.langCodeStyleSettingsProvider` extension point. ```xml - ``` diff --git a/tutorials/custom_language_support/commenter.md b/tutorials/custom_language_support/commenter.md index ed0eb5465..a88a12e50 100644 --- a/tutorials/custom_language_support/commenter.md +++ b/tutorials/custom_language_support/commenter.md @@ -4,7 +4,7 @@ title: 17. Commenter A commenter enables the user to comment-out a line of code at the cursor or selected code automatically. -The [`Commenter`](upsource:///platform/core-api/src/com/intellij/lang/Commenter.java) defines support for **Code \| Comment with Line Comment** and **Code \| Comment with Block Comment** actions. +The [`Commenter`](upsource:///platform/core-api/src/com/intellij/lang/Commenter.java) defines support for **Code \| Comment with Line Comment** and **Code \| Comment with Block Comment** actions. * bullet list {:toc} @@ -17,7 +17,7 @@ The commenter for Simple Language defines the line comment prefix as `#`. ``` ## 17.2. Register the Commenter -The `SimpleCommenter` implementation is registered in the plugin configuration file using the `com.intellij.lang.commenter` extension point. +The `SimpleCommenter` implementation is registered in the plugin configuration file using the `com.intellij.lang.commenter` extension point. ```xml diff --git a/tutorials/custom_language_support/completion_contributor.md b/tutorials/custom_language_support/completion_contributor.md index aa1f97407..49831cd77 100644 --- a/tutorials/custom_language_support/completion_contributor.md +++ b/tutorials/custom_language_support/completion_contributor.md @@ -5,7 +5,7 @@ title: 9. Completion Contributor Custom languages provide code completion using one of two approaches: Contributor and Reference-based (see [10. Reference Contributor](reference_contributor.md)) completion. -**Reference**: [Code Completion](/reference_guide/custom_language_support/code_completion.md) +**Reference**: [Code Completion](/reference_guide/custom_language_support/code_completion.md) * bullet list {:toc} @@ -24,14 +24,14 @@ The `SimpleCompletionContributor` implementation is registered in the plugin con ```xml - ``` ## 9.3. Run the Project Run the `simple_language_plugin` in a Development Instance and open the [`test.simple`](/tutorials/custom_language_support/lexer_and_parser_definition.md#run-the-project) file. -Erase the property "English" and invoke [Basic Code Completion](https://www.jetbrains.com/help/idea/auto-completing-code.html#invoke-basic-completion). +Erase the property "English" and invoke [Basic Code Completion](https://www.jetbrains.com/help/idea/auto-completing-code.html#invoke-basic-completion). The choice "Hello" is shown: ![Completion](img/completion.png) diff --git a/tutorials/custom_language_support/find_usages_provider.md b/tutorials/custom_language_support/find_usages_provider.md index ccdaea872..bb974caa4 100644 --- a/tutorials/custom_language_support/find_usages_provider.md +++ b/tutorials/custom_language_support/find_usages_provider.md @@ -6,13 +6,13 @@ title: 11. Find Usages Provider A `FindUsagesProvider` uses a word scanner to build an index of words in every file. A scanner breaks the text into words and defines the context for each word. -**Reference**: [Find Usages](/reference_guide/custom_language_support/find_usages.md) +**Reference**: [Find Usages](/reference_guide/custom_language_support/find_usages.md) * bullet list {:toc} ## 11.1. Define a Find Usages Provider -The `SimpleFindUsagesProvider` implements [`FindUsagesProvider`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java). +The `SimpleFindUsagesProvider` implements [`FindUsagesProvider`](upsource:///platform/indexing-api/src/com/intellij/lang/findUsages/FindUsagesProvider.java). Using the [`DefaultWordsScanner`](upsource:///platform/indexing-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java) ensures the scanner implementation is thread-safe. See the comments in `FindUsagesProvider` for more information. @@ -25,7 +25,7 @@ The `SimpleFindUsagesProvider` implementation is registered with the IntelliJ Pl ```xml - ``` diff --git a/tutorials/custom_language_support/folding_builder.md b/tutorials/custom_language_support/folding_builder.md index 48a3a79b1..dfdd007f9 100644 --- a/tutorials/custom_language_support/folding_builder.md +++ b/tutorials/custom_language_support/folding_builder.md @@ -16,7 +16,7 @@ Start by subclassing [`FoldingBuilderEx`](upsource:///platform/core-api/src/com/ Note that `SimpleFoldingBuilder` also implements [`DumbAware`](upsource:///platform/core-api/src/com/intellij/openapi/project/DumbAware.java), which means the class is allowed to run in dumb mode, when indices are in background update. -> **NOTE** A folding builder must implement [`DumbAware`](upsource:///platform/core-api/src/com/intellij/openapi/project/DumbAware.java) to function in this tutorial and pass tests. +> **NOTE** A folding builder must implement [`DumbAware`](upsource:///platform/core-api/src/com/intellij/openapi/project/DumbAware.java) to function in this tutorial and pass tests. The `buildFoldRegions()` method searches down a PSI tree from `root` to find all literal expressions containing the [simple prefix](/tutorials/custom_language_support/annotator.md#define-an-annotator) `simple:`. The remainder of such a string is expected to contain a Simple Language key, and so the text range is stored as a [`FoldingDescriptor`](upsource:///platform/core-api/src/com/intellij/lang/folding/FoldingDescriptor.java). @@ -33,7 +33,7 @@ The `SimpleFoldingBuilder` implementation is registered with the IntelliJ Platfo ```xml - ``` diff --git a/tutorials/custom_language_support/formatter.md b/tutorials/custom_language_support/formatter.md index d35586acd..47bfb858e 100644 --- a/tutorials/custom_language_support/formatter.md +++ b/tutorials/custom_language_support/formatter.md @@ -7,14 +7,14 @@ The IntelliJ Platform includes a powerful framework for implementing formatting A formatter enables reformatting code automatically based on code style settings. The formatter controls spaces, indents, wrap, and alignment. -**Reference**: [Code Formatter](/reference_guide/custom_language_support/code_formatting.md) +**Reference**: [Code Formatter](/reference_guide/custom_language_support/code_formatting.md) * bullet list {:toc} ## 15.1. Define a Block The formatting model represents the formatting structure of a file as a tree of [`Block`](upsource:///platform/lang-api/src/com/intellij/formatting/Block.java) objects, with associated indent, wrap, alignment and spacing settings. -The goal is to cover each PSI element with such a block. +The goal is to cover each PSI element with such a block. Since each block builds its children's blocks, it can generate extra blocks or skip any PSI elements. Define `SimpleBlock` based on [`AbstractBlock`](upsource:///platform/lang-impl/src/com/intellij/psi/formatter/common/AbstractBlock.java). @@ -33,11 +33,11 @@ Create `SimpleFormattingModelBuilder` by subclassing [`FormattingModelBuilder`]( ``` ## 15.3. Register the Formatter -The `SimpleFormattingModelBuilder` implementation is registered with the IntelliJ Platform in the plugin configuration file using the `com.intellij.lang.formatter` extension point. +The `SimpleFormattingModelBuilder` implementation is registered with the IntelliJ Platform in the plugin configuration file using the `com.intellij.lang.formatter` extension point. ```xml - ``` diff --git a/tutorials/custom_language_support/go_to_symbol_contributor.md b/tutorials/custom_language_support/go_to_symbol_contributor.md index 7066b5ef1..880bacf02 100644 --- a/tutorials/custom_language_support/go_to_symbol_contributor.md +++ b/tutorials/custom_language_support/go_to_symbol_contributor.md @@ -5,7 +5,7 @@ title: 13. Go To Symbol Contributor A _Go to Symbol Contributor_ helps the user to navigate to any PSI element by its name. -**Reference**: [Go to Class and Go to Symbol](/reference_guide/custom_language_support/go_to_class_and_go_to_symbol.md) +**Reference**: [Go to Class and Go to Symbol](/reference_guide/custom_language_support/go_to_class_and_go_to_symbol.md) * bullet list {:toc} @@ -41,13 +41,13 @@ public static ItemPresentation getPresentation(final SimpleProperty element) { ## 13.2. Update Grammar and Regenerate the Parser Now add the `SimplePsiImplUtil.getPresentation()` to the `property` methods definition in the `Simple.bnf` grammar file by replacing the `property` definition with the lines below. -Don't forget to regenerate the parser after updating the file! +Don't forget to regenerate the parser after updating the file! Right-click on the `Simple.bnf` file and select **Generate Parser Code**. ```java property ::= (KEY? SEPARATOR VALUE?) | KEY { mixin="org.intellij.sdk.language.psi.impl.SimpleNamedElementImpl" - implements="org.intellij.sdk.language.psi.SimpleNamedElement" + implements="org.intellij.sdk.language.psi.SimpleNamedElement" methods=[getKey getValue getName setName getNameIdentifier getPresentation] } ``` @@ -64,7 +64,7 @@ The `SimpleChooseByNameContributor` implementation is registered with the Intell ```xml - ``` diff --git a/tutorials/custom_language_support/grammar_and_parser.md b/tutorials/custom_language_support/grammar_and_parser.md index 99dd39ce8..34354c466 100644 --- a/tutorials/custom_language_support/grammar_and_parser.md +++ b/tutorials/custom_language_support/grammar_and_parser.md @@ -3,10 +3,10 @@ title: 3. Grammar and Parser --- -In order for the IntelliJ Platform to parse a Simple Language file, tokens and elements must be defined based on [`IElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IElementType.java). +In order for the IntelliJ Platform to parse a Simple Language file, tokens and elements must be defined based on [`IElementType`](upsource:///platform/core-api/src/com/intellij/psi/tree/IElementType.java). The Simple Language grammar must also be defined to generate a parser. - -**Reference**: [Implementing a Parser and PSI](/reference_guide/custom_language_support/implementing_parser_and_psi.md) + +**Reference**: [Implementing a Parser and PSI](/reference_guide/custom_language_support/implementing_parser_and_psi.md) * bullet item {:toc} diff --git a/tutorials/custom_language_support/language_and_filetype.md b/tutorials/custom_language_support/language_and_filetype.md index 1c447719a..a21347ee7 100644 --- a/tutorials/custom_language_support/language_and_filetype.md +++ b/tutorials/custom_language_support/language_and_filetype.md @@ -5,9 +5,9 @@ title: 2. Language and File Type The IntelliJ Platform determines file type by examining the name of a file. Each language has [Language](upsource:///platform/core-api/src/com/intellij/lang/Language.java) and [LanguageFileType](upsource:///platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java) objects defining the language. -Register the `LanguageFileType` with the IntelliJ Platform in the plugin configuration file. +Register the `LanguageFileType` with the IntelliJ Platform in the plugin configuration file. -**Reference**: [Registering a File Type](/reference_guide/custom_language_support/registering_file_type.md) +**Reference**: [Registering a File Type](/reference_guide/custom_language_support/registering_file_type.md) * bullet item {:toc} @@ -21,9 +21,9 @@ The `SimpleLanguage` class is defined in the `org.intellij.sdk.language` package ``` ## 2.2. Define an Icon -The [icon](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/simple_language_plugin/src/main/resources/icons/jar-gray.png) for the Simple Language is defined by the `SimpleIcons` class. +The [icon](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/simple_language_plugin/src/main/resources/icons/jar-gray.png) for the Simple Language is defined by the `SimpleIcons` class. There is nothing uniquely Simple Language-specific about [defining the icon](/reference_guide/work_with_icons_and_images.md) itself. -The definition follows a pattern similar to defining, e.g., `SdkIcons`. +The definition follows a pattern similar to defining, e.g., `SdkIcons`. ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/SimpleIcons.java %} @@ -39,11 +39,11 @@ The Simple Language file type is defined by subclassing [`LanguageFileType`](ups ## 2.4. Register the FileType Directly Direct registration is possible when targeting version 2019.2 (and later) of the IntelliJ Platform - no `FileTypeFactory` is required. -Instead, the file type is registered via the `com.intellij.fileType` extension point in `plugin.xml`: +Instead, the file type is registered via the `com.intellij.fileType` extension point in `plugin.xml`: ```xml - ``` diff --git a/tutorials/custom_language_support/lexer_and_parser_definition.md b/tutorials/custom_language_support/lexer_and_parser_definition.md index 9e10bde85..62525bb6a 100644 --- a/tutorials/custom_language_support/lexer_and_parser_definition.md +++ b/tutorials/custom_language_support/lexer_and_parser_definition.md @@ -6,7 +6,7 @@ title: 4. Lexer and Parser Definition The lexical analyzer defines how the contents of a file are broken into tokens, which is the basis for supporting custom language features. The easiest way to create a lexer is to use [JFlex](https://jflex.de/). -**Reference**: [Implementing Lexer](/reference_guide/custom_language_support/implementing_lexer.md) +**Reference**: [Implementing Lexer](/reference_guide/custom_language_support/implementing_lexer.md) * bullet item {:toc} @@ -46,7 +46,7 @@ See [Implementing Lexer](/reference_guide/custom_language_support/implementing_l ## 4.3. Define a Lexer Adapter The JFlex lexer needs to be adapted to the IntelliJ Platform Lexer API. -This is done by subclassing [`FlexAdapter`](upsource:///platform/core-api/src/com/intellij/lexer/FlexAdapter.java). +This is done by subclassing [`FlexAdapter`](upsource:///platform/core-api/src/com/intellij/lexer/FlexAdapter.java). ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/SimpleLexerAdapter.java %} @@ -60,7 +60,7 @@ The `SimpleFile` implementation is the top-level node of the [tree of `PsiElemen ``` ## 4.5. Define a Parser -The Simple Language parser is defined by subclassing [`ParserDefinition`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java). +The Simple Language parser is defined by subclassing [`ParserDefinition`](upsource:///platform/core-api/src/com/intellij/lang/ParserDefinition.java). ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/SimpleParserDefinition.java %} @@ -73,13 +73,13 @@ For example, see `simple_language_plugin/src/main/resources/META-INF/plugin.xml` ```xml - ``` ## 4.7. Run the Project -With the `simple_language_plugin` loaded in a Development Instance, create a `test.simple` properties file with the following content: +With the `simple_language_plugin` loaded in a Development Instance, create a `test.simple` properties file with the following content: ```text # You are reading the ".properties" entry. diff --git a/tutorials/custom_language_support/line_marker_provider.md b/tutorials/custom_language_support/line_marker_provider.md index 4cca4d093..4548f0d50 100644 --- a/tutorials/custom_language_support/line_marker_provider.md +++ b/tutorials/custom_language_support/line_marker_provider.md @@ -14,7 +14,7 @@ A line marker provider annotates usages of Simple Language properties within Jav The visual marker is a Simple Language icon in the gutter of the Editor window. The Simple Language marker provider subclasses [`RelatedItemLineMarkerProvider`](upsource:///platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerProvider.java). -For this example, override the `collectNavigationMarkers()` method to collect usage of a Simple Language [key and separators](/tutorials/custom_language_support/language_and_filetype.md#define-the-language): +For this example, override the `collectNavigationMarkers()` method to collect usage of a Simple Language [key and separators](/tutorials/custom_language_support/language_and_filetype.md#define-the-language): ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/SimpleLineMarkerProvider.java %} @@ -23,12 +23,12 @@ For this example, override the `collectNavigationMarkers()` method to collect us ## 8.2. Best Practices for Implementing Line Marker Providers This section addresses important details about implementing a marker provider. The `collectNavigationMarkers()` method should: -* Only return line marker information consistent with the element passed into the method. +* Only return line marker information consistent with the element passed into the method. For example, do not return a _class_ marker if `getLineMarkerInfo()` was called with an element that corresponds to a _method_. -* Return line marker information for the appropriate element at the correct scope of the PSI tree. - For example, do not return method marker for [`PsiMethod`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiMethod.java). - Instead, return it for the [`PsiIdentifier`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiIdentifier.java) which contains the name of the method. - +* Return line marker information for the appropriate element at the correct scope of the PSI tree. + For example, do not return method marker for [`PsiMethod`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiMethod.java). + Instead, return it for the [`PsiIdentifier`](upsource:///java/java-psi-api/src/com/intellij/psi/PsiIdentifier.java) which contains the name of the method. + ![Line Marker Location](img/line_marker_location.png){:width="900px"} What happens when a `LineMarkerProvider` returns marker information for a `PsiElement` that is a higher node in the PSI tree? @@ -50,8 +50,8 @@ For performance reasons, inspection, and specifically the [`LineMarkersPass`](up If providers return nothing for either area, the line markers get cleared. However, if a method like `actionPerformed()` is not completely visible in the Editor window (as shown in the image above,) and `MyWrongLineMarkerProvider()` returns marker info for the `PsiMethod` instead of `PsiIdentifier`, then: -* The first pass removes line marker info because whole `PsiMethod` isn't visible. -* The second pass tries to add a line marker because `MyWrongLineMarkerProvider()` is called for the `PsiMethod`. +* The first pass removes line marker info because whole `PsiMethod` isn't visible. +* The second pass tries to add a line marker because `MyWrongLineMarkerProvider()` is called for the `PsiMethod`. As a result, _the line marker icon would blink annoyingly_. To fix this problem, rewrite `MyWrongLineMarkerProvider` to return info for `PsiIdentifier` instead of `PsiMethod` as shown below: @@ -70,7 +70,7 @@ The `SimpleLineMarkerProvider` implementation is registered with the IntelliJ Pl ```xml - ``` diff --git a/tutorials/custom_language_support/prerequisites.md b/tutorials/custom_language_support/prerequisites.md index 9b3c5586c..5569256db 100644 --- a/tutorials/custom_language_support/prerequisites.md +++ b/tutorials/custom_language_support/prerequisites.md @@ -7,7 +7,7 @@ title: 1. Prerequisites Download and install either IntelliJ IDEA Ultimate or IntelliJ IDEA Community Edition from [here](https://www.jetbrains.com/idea/download/). ### 1.2. Check out Community Edition Source Files -> **NOTE** While not required, having the full sources of the platform and all bundled plugins available for browsing allows finding related implementations. +> **NOTE** While not required, having the full sources of the platform and all bundled plugins available for browsing allows finding related implementations. Download the IntelliJ IDEA Community Edition source files as described in the IntelliJ IDEA Community Edition [README](upsource:///README.md) file. @@ -17,4 +17,3 @@ Install and enable [Grammar-Kit](https://plugins.jetbrains.com/plugin/6606-gramm ### 1.4. Create a Project Create an [IntelliJ Platform Plugin project](/tutorials/build_system/prerequisites.md). - diff --git a/tutorials/custom_language_support/psi_helper_and_utilities.md b/tutorials/custom_language_support/psi_helper_and_utilities.md index 8ad77423a..590f0dfda 100644 --- a/tutorials/custom_language_support/psi_helper_and_utilities.md +++ b/tutorials/custom_language_support/psi_helper_and_utilities.md @@ -6,7 +6,7 @@ title: 6. PSI Helpers and Utilities Helper classes and utilities can be embedded in the code generated by Grammar-Kit. * bullet item -{:toc} +{:toc} ## 6.1. Define Helper Methods for Generated PSI Elements Custom methods in PSI classes are defined separately, and Grammar-Kit embeds them into generated code. @@ -27,7 +27,7 @@ public class SimplePsiImplUtil { return null; } } - + public static String getValue(SimpleProperty element) { ASTNode valueNode = element.getNode().findChildByType(SimpleTypes.VALUE); if (valueNode != null) { @@ -39,7 +39,7 @@ public class SimplePsiImplUtil { } ``` -The parser generates the `SimpleProperty` interface referenced in the code above. +The parser generates the `SimpleProperty` interface referenced in the code above. ## 6.2. Update Grammar and Regenerate the Parser Now the utility class is added to the grammar file via the `psiImplUtilClass` attribute. @@ -80,4 +80,3 @@ This utility will be used later when implementing [code completion](https://www. ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/SimpleUtil.java %} ``` - diff --git a/tutorials/custom_language_support/quick_fix.md b/tutorials/custom_language_support/quick_fix.md index 0f322cdda..a767fb304 100644 --- a/tutorials/custom_language_support/quick_fix.md +++ b/tutorials/custom_language_support/quick_fix.md @@ -3,17 +3,17 @@ title: 18. Quick Fix --- -A quick fix for a custom language supports the IntelliJ Platform-based IDE feature [Intention Actions](https://www.jetbrains.com/help/idea/intention-actions.html#apply-intention-actions). +A quick fix for a custom language supports the IntelliJ Platform-based IDE feature [Intention Actions](https://www.jetbrains.com/help/idea/intention-actions.html#apply-intention-actions). For the Simple Language, this tutorial adds a quick fix that helps to define an unresolved property from its usage. -**Reference**: [Code Inspections and Intentions](/reference_guide/custom_language_support/code_inspections_and_intentions.md) +**Reference**: [Code Inspections and Intentions](/reference_guide/custom_language_support/code_inspections_and_intentions.md) * bullet list {:toc} ## 18.1. Update the Element Factory The `SimpleElementFactory` is updated to include two new methods to support the user choice of creating a new property for the Simple Language quick fix. -The new `createCRLF()` method supports adding a newline to the end of the [`test.simple`](/tutorials/custom_language_support/lexer_and_parser_definition.md#run-the-project) file before adding a new property. +The new `createCRLF()` method supports adding a newline to the end of the [`test.simple`](/tutorials/custom_language_support/lexer_and_parser_definition.md#run-the-project) file before adding a new property. A new overload of `createProperty()` creates a new `key`-`value` pair for Simple Language. ```java @@ -23,7 +23,7 @@ A new overload of `createProperty()` creates a new `key`-`value` pair for Simple ## 18.2. Define an Intention Action The `SimpleCreatePropertyQuickFix` creates a property in the file chosen by the user - in this case, a Java file containing a `prefix:key` - and navigate to this property after creation. Under the hood, `SimpleCreatePropertyQuickFix` is an Intention Action. -For a more in-depth example of an Intention Action, see [`conditional_operator_intention`](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/conditional_operator_intention). +For a more in-depth example of an Intention Action, see [`conditional_operator_intention`](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/conditional_operator_intention). ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/SimpleCreatePropertyQuickFix.java %} @@ -31,7 +31,7 @@ For a more in-depth example of an Intention Action, see [`conditional_operator_i ## 18.3. Update the Annotator When a `badProperty` annotation is created, the `badProperty.registerFix()` method is called. -This method call registers the `SimpleCreatePropertyQuickFix` as the Intention Action for the Intellij Platform to use to correct the problem. +This method call registers the `SimpleCreatePropertyQuickFix` as the Intention Action for the Intellij Platform to use to correct the problem. ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/SimpleAnnotator.java %} @@ -42,7 +42,7 @@ Open the test [Java file](/tutorials/custom_language_support/annotator.md#run-th To test `SimpleCreatePropertyQuickFix`, change `simple:website` to `simple:website.url`. The key `website.url` is highlighted by `SimpleAnnotator` as an invalid key, as shown below. -Choose "Create Property". +Choose "Create Property". ![Quick Fix](img/quick_fix.png){:width="800px"} @@ -51,4 +51,4 @@ Add the new value `jetbrains.com` for the new `website.url` key. ![New Property](img/new_property.png) -Now switch back to the Java file; the new key is highlighted as valid. +Now switch back to the Java file; the new key is highlighted as valid. diff --git a/tutorials/custom_language_support/reference_contributor.md b/tutorials/custom_language_support/reference_contributor.md index 0a436ee1d..ce09a00c9 100644 --- a/tutorials/custom_language_support/reference_contributor.md +++ b/tutorials/custom_language_support/reference_contributor.md @@ -8,7 +8,7 @@ Resolving references means the ability to go from the usage of an element to its > **NOTE** Every PSI element that can be renamed or referenced needs to implement [`PsiNamedElement`](upsource:///platform/core-api/src/com/intellij/psi/PsiNamedElement.java) interface. -**Reference**: [References and Resolve](/reference_guide/custom_language_support/references_and_resolve.md) +**Reference**: [References and Resolve](/reference_guide/custom_language_support/references_and_resolve.md) * bullet list {:toc} @@ -21,16 +21,16 @@ The `SimpleNamedElement` interface is subclassed from [`PsiNameIdentifierOwner`] ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/psi/SimpleNamedElement.java %} ``` - + The `SimpleNamedElementImpl` class implements the `SimpleNamedElement` interface and extends [`ASTWrapperPsiElement`](upsource:///platform/core-impl/src/com/intellij/extapi/psi/ASTWrapperPsiElement.java). ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/psi/impl/SimpleNamedElementImpl.java %} ``` - + ## 10.2. Define Helper Methods for Generated PSI Elements -Modify `SimplePsiImplUtil` to support new methods that get added to the PSI class for Simple Language. -Note that `SimpleElementFactory` isn't defined until the [next step](#define-an-element-factory), so for now it shows as an error. +Modify `SimplePsiImplUtil` to support new methods that get added to the PSI class for Simple Language. +Note that `SimpleElementFactory` isn't defined until the [next step](#define-an-element-factory), so for now it shows as an error. ```java public class SimplePsiImplUtil { @@ -91,20 +91,20 @@ public class SimpleElementFactory { ## 10.4. Update Grammar and Regenerate the Parser Now make corresponding changes to the `Simple.bnf` grammar file by replacing the `property` definition with the lines below. -Don't forget to regenerate the parser after updating the file! +Don't forget to regenerate the parser after updating the file! Right-click on the `Simple.bnf` file and select **Generate Parser Code**. ```java property ::= (KEY? SEPARATOR VALUE?) | KEY { mixin="org.intellij.sdk.language.psi.impl.SimpleNamedElementImpl" - implements="org.intellij.sdk.language.psi.SimpleNamedElement" + implements="org.intellij.sdk.language.psi.SimpleNamedElement" methods=[getKey getValue getName setName getNameIdentifier] } ``` ## 10.5. Define a Reference Now define a reference class to resolve a property from its usage. -This requires extending [`PsiReferenceBase`](upsource:///platform/core-api/src/com/intellij/psi/PsiReferenceBase.java) and implementing [`PsiPolyVariantReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiPolyVariantReference.java). +This requires extending [`PsiReferenceBase`](upsource:///platform/core-api/src/com/intellij/psi/PsiReferenceBase.java) and implementing [`PsiPolyVariantReference`](upsource:///platform/core-api/src/com/intellij/psi/PsiPolyVariantReference.java). The latter enables the reference to resolve to more than one element or to resolve result(s) for a superset of valid resolve cases. ```java @@ -153,7 +153,7 @@ The `SimpleRefactoringSupportProvider` implementation is registered with the Int ```xml - ``` diff --git a/tutorials/custom_language_support/structure_view_factory.md b/tutorials/custom_language_support/structure_view_factory.md index 49a8f17a9..e4c361497 100644 --- a/tutorials/custom_language_support/structure_view_factory.md +++ b/tutorials/custom_language_support/structure_view_factory.md @@ -6,7 +6,7 @@ title: 14. Structure View Factory The structure view can be customized for a specific file type. Creating a structure view factory allows showing the structure of any file in a _Structure_ Tool Window for easy navigation between items in the current editor. -**Reference**: [Structure View](/reference_guide/custom_language_support/structure_view.md) +**Reference**: [Structure View](/reference_guide/custom_language_support/structure_view.md) * bullet list {:toc} @@ -21,7 +21,7 @@ At this point the project will not compile until `SimpleStructureViewModel` is [ ``` ## 14.2. Define a Structure View Model -The `SimpleStructureViewModel` is created by implementing [`StructureViewModel`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureViewModel.java), which defines the model for data displayed in the standard structure view. +The `SimpleStructureViewModel` is created by implementing [`StructureViewModel`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureViewModel.java), which defines the model for data displayed in the standard structure view. It also extends [`StructureViewModelBase`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureViewModelBase.java), an implementation that links the model to a text editor. ```java @@ -31,7 +31,7 @@ It also extends [`StructureViewModelBase`](upsource:///platform/editor-ui-api/sr ## 14.3. Define a Structure View Element The `SimpleStructureViewElement` implements [`StructureViewTreeElement`](upsource:///platform/editor-ui-api/src/com/intellij/ide/structureView/StructureViewTreeElement.java) and [`SortableTreeElement`](upsource:///platform/editor-ui-api/src/com/intellij/ide/util/treeView/smartTree/SortableTreeElement.java). The `StructureViewTreeElement` represents an element in the Structure View tree model. -The `SortableTreeElement` represents an item in a smart tree that allows using text other than the presentable text as a key for alphabetic sorting. +The `SortableTreeElement` represents an item in a smart tree that allows using text other than the presentable text as a key for alphabetic sorting. ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/SimpleStructureViewElement.java %} @@ -42,7 +42,7 @@ The `SimpleStructureViewFactory` implementation is registered with the IntelliJ ```xml - ``` diff --git a/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md b/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md index 1cc1b8d67..ae2e998b4 100644 --- a/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md +++ b/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md @@ -7,14 +7,14 @@ The first level of syntax highlighting is based on the lexer output, and is prov A plugin can also define color settings based on `ColorSettingPage` so the user can configure highlight colors. The `SimpleSyntaxHighlighter`, `SimpleSyntaxHighlighterFactory`, and `SimpleColorSettingsPage` discussed on this page are demonstrated in the `simple_language_plugin` code sample. -**Reference**: [Syntax Highlighting and Error Highlighting](/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md) +**Reference**: [Syntax Highlighting and Error Highlighting](/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md) * bullet list {:toc} -## 5.1. Define a Syntax Highlighter +## 5.1. Define a Syntax Highlighter The Simple Language syntax highlighter class extends [`SyntaxHighlighterBase`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighterBase.java). -As recommended in [Color Scheme Management](/reference_guide/color_scheme_management.md#text-attribute-key-dependency), the Simple Language highlighting text attributes are specified as a dependency on one of standard Intellij Platform keys. +As recommended in [Color Scheme Management](/reference_guide/color_scheme_management.md#text-attribute-key-dependency), the Simple Language highlighting text attributes are specified as a dependency on one of standard Intellij Platform keys. For the Simple Language, define only one scheme. ```java @@ -34,7 +34,7 @@ Register the factory with the IntelliJ Platform in the plugin configuration file ```xml - ``` @@ -46,15 +46,15 @@ The colors for Simple Language Key, Separator, and Value highlighting default to ![Syntax highlighter](img/syntax_highlighter.png) ## 5.5. Define a Color Settings Page -The color settings page adds the ability for users to customize color settings for the highlighting in Simple Language files. -The `SimpleColorSettingsPage` implements [`ColorSettingsPage`](upsource:///platform/platform-api/src/com/intellij/openapi/options/colors/ColorSettingsPage.java). +The color settings page adds the ability for users to customize color settings for the highlighting in Simple Language files. +The `SimpleColorSettingsPage` implements [`ColorSettingsPage`](upsource:///platform/platform-api/src/com/intellij/openapi/options/colors/ColorSettingsPage.java). ```java {% include /code_samples/simple_language_plugin/src/main/java/org/intellij/sdk/language/SimpleColorSettingsPage.java %} ``` ### 5.6. Register the Color Settings Page -Register the Simple Language color settings page with the IntelliJ Platform in the plugin configuration file using the `com.intellij.colorSettingsPage` extension point. +Register the Simple Language color settings page with the IntelliJ Platform in the plugin configuration file using the `com.intellij.colorSettingsPage` extension point. ```xml diff --git a/tutorials/custom_language_support_tutorial.md b/tutorials/custom_language_support_tutorial.md index 921e78353..5fda06a9c 100644 --- a/tutorials/custom_language_support_tutorial.md +++ b/tutorials/custom_language_support_tutorial.md @@ -5,11 +5,11 @@ title: Custom Language Support Tutorial In this tutorial we will add support for a [.properties](https://en.wikipedia.org/wiki/.properties) language and its usages within Java code. -> **TIP** IntelliJ Platform support for custom languages is discussed in more depth in the [Custom Language Support](/reference_guide/custom_language_support.md) section. +> **TIP** IntelliJ Platform support for custom languages is discussed in more depth in the [Custom Language Support](/reference_guide/custom_language_support.md) section. > Corresponding parts are linked under "Reference" on top of each page in this tutorial. - + The example plugin used in this tutorial is the [`simple_language_plugin`](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/simple_language_plugin) code sample. -This a step-by-step tutorial, and it requires completing each step, in order: +This a step-by-step tutorial, and it requires completing each step, in order: * [1. Prerequisites](custom_language_support/prerequisites.md) * [2. Language and File Type](custom_language_support/language_and_filetype.md) diff --git a/tutorials/editor_basics.md b/tutorials/editor_basics.md index 256f70aee..913b96911 100644 --- a/tutorials/editor_basics.md +++ b/tutorials/editor_basics.md @@ -3,15 +3,15 @@ title: Basics of Working with the Editor --- -This tutorial will lead you through the series of steps showing how to work with the IntelliJ Platform Editor, how to access and modify text it contains, and how to handle events sent to the editor. +This tutorial will lead you through the series of steps showing how to work with the IntelliJ Platform Editor, how to access and modify text it contains, and how to handle events sent to the editor. * [1. Working With Text](editor_basics/working_with_text.md) * [2. Editor coordinate systems: positions and offsets](editor_basics/coordinates_system.md) * [3. Handling Editor Events](editor_basics/editor_events.md) -**Note:** The part of the API described in this tutorial only allows operations with text. +**Note:** The part of the API described in this tutorial only allows operations with text. For operations that require access to the PSI please see the [PSI Cookbook](/basics/psi_cookbook.md) section. -**See also:** +**See also:** The following are referenced in the tutorial: * The [editor_basics](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/editor_basics/) plugin code sample, * [editor-ui-api package](upsource:///platform/editor-ui-api), @@ -21,7 +21,6 @@ The following are referenced in the tutorial: * [`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java), * [`TypedAction`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java). -**Related topics:** +**Related topics:** * [Action System](/tutorials/action_system.md) * [Threading Issues](/basics/architectural_overview/general_threading_rules.md) - diff --git a/tutorials/editor_basics/coordinates_system.md b/tutorials/editor_basics/coordinates_system.md index bac017bf6..1c8b2405c 100644 --- a/tutorials/editor_basics/coordinates_system.md +++ b/tutorials/editor_basics/coordinates_system.md @@ -3,28 +3,28 @@ title: Editor Coordinate Systems - Caret Positions and Offsets --- -The previous tutorial [Working with Text](working_with_text.md) demonstrated how to use actions to access a caret placed in a document open in an editor. +The previous tutorial [Working with Text](working_with_text.md) demonstrated how to use actions to access a caret placed in a document open in an editor. The examples replaced selected text in a document by using information about the caret. -Every caret has a set of properties describing its position in one of several coordinate systems. -This tutorial describes how to access information about the caret(s) in an editor. +Every caret has a set of properties describing its position in one of several coordinate systems. +This tutorial describes how to access information about the caret(s) in an editor. The tutorial presents the following sections: * bullet list {:toc} ## Introduction -In this tutorial, the [editor_basics](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/editor_basics) code sample is used to explore caret positions. -In particular, the **Caret Position** action added by `editor_basics` to the editor context menu is used to retrieve information about the current caret position. -A keyboard shortcut can also initiate the action. +In this tutorial, the [editor_basics](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/editor_basics) code sample is used to explore caret positions. +In particular, the **Caret Position** action added by `editor_basics` to the editor context menu is used to retrieve information about the current caret position. +A keyboard shortcut can also initiate the action. ![Editor Basics Menu](img/basics.png){:width="600px"} -The source code for the Java class behind the menu action is [EditorAreaIllustration](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/editor_basics/src/main/java/org/intellij/sdk/editor/EditorAreaIllustration.java). -The focus of discussion will be the `EditorAreaIllustration.actionPerformed()` method. +The source code for the Java class behind the menu action is [EditorAreaIllustration](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/editor_basics/src/main/java/org/intellij/sdk/editor/EditorAreaIllustration.java). +The focus of discussion will be the `EditorAreaIllustration.actionPerformed()` method. For more information about creating action classes, see the [Actions Tutorial](/tutorials/action_system.md) which covers the topic in depth. ## Caret Positions from the CaretModel and Caret Objects -The properties of a caret can be accessed by obtaining an instance of the [`CaretModel`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/CaretModel.java) object. +The properties of a caret can be accessed by obtaining an instance of the [`CaretModel`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/CaretModel.java) object. As in the [Working with Text](working_with_text.md) tutorial, the `AnActionEvent` is used to get the `Editor` object. The `Editor` object provides access to the `CaretModel` object, as shown below: @@ -40,63 +40,63 @@ public class EditorAreaIllustration extends AnAction { ``` ## Editor Coordinate Systems -When a `Document` is opened, the `Editor` assigns an internal, zero-based coordinate system to lines and columns in the `Document`. -The first line in a `Document` and the first character in each line are assigned the zero position. -Every character in a `Document` is assigned an [_Offset_](#caret-offset), which is a zero-based count of the characters from the beginning of the file to that character. -These [LogicalPosition](#caret-logical-position) coordinates are used to describe the line and column number for a caret position. +When a `Document` is opened, the `Editor` assigns an internal, zero-based coordinate system to lines and columns in the `Document`. +The first line in a `Document` and the first character in each line are assigned the zero position. +Every character in a `Document` is assigned an [_Offset_](#caret-offset), which is a zero-based count of the characters from the beginning of the file to that character. +These [LogicalPosition](#caret-logical-position) coordinates are used to describe the line and column number for a caret position. Note that the Logical Position coordinate system is different from the editor UI, which is one-based rather than zero-based. -Logical Position coordinates and other coordinate systems discussed in this tutorial can be used to characterize any location in an `Editor`, not just carets. -Hints used for code insights are characterized in terms of these coordinates, for example [`HintManager.getHintPosition()`](upsource:///platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java). +Logical Position coordinates and other coordinate systems discussed in this tutorial can be used to characterize any location in an `Editor`, not just carets. +Hints used for code insights are characterized in terms of these coordinates, for example [`HintManager.getHintPosition()`](upsource:///platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java). Custom visual elements displayed in an `Editor`, called [`Inlay`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/Inlay.java) objects, are also expressed in terms of these coordinate systems. -The diagram below shows the Logical Position coordinate system applied to some example content. -The character "s" in the red box represents placing the cursor on that character. -It has the caret position of line 1, column 9, and Offset 28. +The diagram below shows the Logical Position coordinate system applied to some example content. +The character "s" in the red box represents placing the cursor on that character. +It has the caret position of line 1, column 9, and Offset 28. More about caret [Offsets](#caret-offset) is discussed below. ![Editor Coordinates](img/editor_coords.png){:width="800px"} -The [Multiple Carets](/reference_guide/multiple_carets.md) documentation covers the subject of more than one caret in an Editor. -For this tutorial, be aware there may be more than one caret in an `Editor` at any given time. -Consequently, examples use the _Primary Caret_ in an `Editor`. -If there is only one caret in an `Editor`, it is the Primary Caret. +The [Multiple Carets](/reference_guide/multiple_carets.md) documentation covers the subject of more than one caret in an Editor. +For this tutorial, be aware there may be more than one caret in an `Editor` at any given time. +Consequently, examples use the _Primary Caret_ in an `Editor`. +If there is only one caret in an `Editor`, it is the Primary Caret. For the case of multiple carets in an `Editor`, the Primary Caret is the one on which query and update methods in the model operate at the moment. ### Caret Logical Position -The caret _Logical Position_ is a zero-based, (line and column) position of the caret in the Editor. -Logical Position information is obtained from the [`LogicalPosition`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/LogicalPosition.java) object for that caret. +The caret _Logical Position_ is a zero-based, (line and column) position of the caret in the Editor. +Logical Position information is obtained from the [`LogicalPosition`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/LogicalPosition.java) object for that caret. -The Logical Position line number of a caret ignores the effects of settings that change the presentation of a `Document` within the Editor. -Examples of these settings are [Code (Line) Folding](https://www.jetbrains.com/help/idea/working-with-source-code.html#code_folding) and [Soft Line Wrap](https://www.jetbrains.com/help/idea/using-code-editor.html#f804afd8). +The Logical Position line number of a caret ignores the effects of settings that change the presentation of a `Document` within the Editor. +Examples of these settings are [Code (Line) Folding](https://www.jetbrains.com/help/idea/working-with-source-code.html#code_folding) and [Soft Line Wrap](https://www.jetbrains.com/help/idea/using-code-editor.html#f804afd8). These effects mean regardless of whether one or more lines in an Editor are folded or soft-wrapped, the caret Logical Position line number will not change. -In the example Java file below, Logical Position line numbers 1-3 are folded into line 0. -The caret - a blue block - is placed on the letter "p" in "public." -Using the `editor_basics` **Caret Position** action to inspect the caret, it is reported to be at Logical Position (5,0) - which is line 5, character 0 - the first character in the line. -This means that caret Logical Position is not changed by Code Folding: +In the example Java file below, Logical Position line numbers 1-3 are folded into line 0. +The caret - a blue block - is placed on the letter "p" in "public." +Using the `editor_basics` **Caret Position** action to inspect the caret, it is reported to be at Logical Position (5,0) - which is line 5, character 0 - the first character in the line. +This means that caret Logical Position is not changed by Code Folding: -![Caret Logical Position with Folding](img/logical_pos_folded.png){:width="800px"} +![Caret Logical Position with Folding](img/logical_pos_folded.png){:width="800px"} -However, note that applying Code Folding _does change the reported Visual Position_ of the caret even if the Logical Position stays constant. -More about [Visual Position](#caret-visual-position) is discussed below. -However, it's clear combinations of Code Folding and Soft Wrap means that one Logical Position of a caret could map to multiple Visual Positions. +However, note that applying Code Folding _does change the reported Visual Position_ of the caret even if the Logical Position stays constant. +More about [Visual Position](#caret-visual-position) is discussed below. +However, it's clear combinations of Code Folding and Soft Wrap means that one Logical Position of a caret could map to multiple Visual Positions. The `Editor` interface provides methods to work with a caret Logical and Visual Position, such as the method `Editor.logicalToVisualPosition()`. ### Caret Visual Position -A caret's _Visual Position_ differs from Logical Position in that it takes into account editor presentation settings such as Code Folding and Soft Line Wrap. -In doing so, [`VisualPosition`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/VisualPosition.java) counts - zero-based - the lines of a `Document` that can be _displayed_ in an Editor. +A caret's _Visual Position_ differs from Logical Position in that it takes into account editor presentation settings such as Code Folding and Soft Line Wrap. +In doing so, [`VisualPosition`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/VisualPosition.java) counts - zero-based - the lines of a `Document` that can be _displayed_ in an Editor. Consequently, Visual Positions can't be uniquely mapped to Logical Positions or corresponding lines in the underlying `Document`. -For example, Soft Line Wrap affects the Visual Position of succeeding lines. -In the image below, Soft Line Wrap is applied to Logical line three. -With the caret placed at the same character location as in previous tests, it is evident the Logical Position has not changed. -However, the Visual Position line number has increased by one! +For example, Soft Line Wrap affects the Visual Position of succeeding lines. +In the image below, Soft Line Wrap is applied to Logical line three. +With the caret placed at the same character location as in previous tests, it is evident the Logical Position has not changed. +However, the Visual Position line number has increased by one! The comments on each line illustrate how the Soft Wrap portion of Logical line three is evaluated as Visual Position line four, as though it was a separate line. -![Caret Visual Position with Soft-Wrap](img/vis_pos_soft_wrap.png){:width="800px"} +![Caret Visual Position with Soft-Wrap](img/vis_pos_soft_wrap.png){:width="800px"} -The Logical and Visual Position objects for a caret are obtained from the [`Caret`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/Caret.java) object, as shown in the code snippet below. +The Logical and Visual Position objects for a caret are obtained from the [`Caret`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/Caret.java) object, as shown in the code snippet below. ```java public class EditorAreaIllustration extends AnAction { @@ -113,8 +113,8 @@ public class EditorAreaIllustration extends AnAction { ``` ### Caret Column Position -The _Column Position_ is a count of characters from the beginning of a Logical (Position) line to the current caret position in that line. -Characters are counted using a zero-based numbering system, so the first character of a line is numbered zero. +The _Column Position_ is a count of characters from the beginning of a Logical (Position) line to the current caret position in that line. +Characters are counted using a zero-based numbering system, so the first character of a line is numbered zero. Note that Column Position is different from the editor UI, which uses a one-based numbering scheme. Column Position includes: @@ -123,40 +123,40 @@ Column Position includes: * The character selected by the caret. #### Caret Lean -The Column Position of a caret is the boundary between two characters. -A caret can be associated with either a preceding or succeeding character. +The Column Position of a caret is the boundary between two characters. +A caret can be associated with either a preceding or succeeding character. The association is important in bidirectional text, where mapping from Logical Column Position to Visual Column Position is not continuous. - -As defined in the [`LogicalPosition`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/LogicalPosition.java) class, if a caret position is associated with a succeeding character it _Leans Forward_. -Otherwise, it is associated with the preceding character. -As defined in the [`VisualPosition`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/VisualPosition.java) class, if a caret position is associated with a succeeding character it _Leans Right_. +As defined in the [`LogicalPosition`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/LogicalPosition.java) class, if a caret position is associated with a succeeding character it _Leans Forward_. +Otherwise, it is associated with the preceding character. + +As defined in the [`VisualPosition`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/VisualPosition.java) class, if a caret position is associated with a succeeding character it _Leans Right_. Otherwise, it is associated with the preceding character. #### Examples of Caret Lean -In the example below, placing a (blue) block caret on the first visible character in Logical line three produces a column position of 0 for both Visual and Logical Positions. -Note that the text is unidirectional in this example. -In the Logical Position the caret leans forward, meaning it is associated with the succeeding character in the Logical line. -For the Visual Position the caret leans right, indicating its association with the succeeding character in the Visual line. +In the example below, placing a (blue) block caret on the first visible character in Logical line three produces a column position of 0 for both Visual and Logical Positions. +Note that the text is unidirectional in this example. +In the Logical Position the caret leans forward, meaning it is associated with the succeeding character in the Logical line. +For the Visual Position the caret leans right, indicating its association with the succeeding character in the Visual line. -![Caret Column Position - Block Caret](img/caret_col_pos_block.png){:width="800px"} +![Caret Column Position - Block Caret](img/caret_col_pos_block.png){:width="800px"} -
+
-Consider the Java snippet below, and use the `editor_basics` **Caret Position** action to report caret information at each step. -Be sure to use the keyboard shortcut to invoke the action so that the caret position is not disturbed. +Consider the Java snippet below, and use the `editor_basics` **Caret Position** action to report caret information at each step. +Be sure to use the keyboard shortcut to invoke the action so that the caret position is not disturbed. -The line containing the `String` variable declaration contains bidirectional text. -Starting on the left end of the line, and using the arrow key to advance a line-shaped cursor to between the `("` characters reveals discontinuities in caret coordinate column positions. -* After the caret first moves from between `g(` to between `("`, the Logical and Visual Positions have equal column positions of 28, and neither leans. +The line containing the `String` variable declaration contains bidirectional text. +Starting on the left end of the line, and using the arrow key to advance a line-shaped cursor to between the `("` characters reveals discontinuities in caret coordinate column positions. +* After the caret first moves from between `g(` to between `("`, the Logical and Visual Positions have equal column positions of 28, and neither leans. Note the value of the caret positions you measure may have different starting values because of line indentation, but the sign and magnitude of the changes in position will be the same. -* Advancing the caret once more does not appear to visually move the cursor. - However, the Logical Position column increases to 61, and although the Visual Position column does not change, it leans right. -* Continuing to advance the cursor (to the right) through the string causes the Logical Position column to _decrease_, and the Visual Position column to _increase_. +* Advancing the caret once more does not appear to visually move the cursor. + However, the Logical Position column increases to 61, and although the Visual Position column does not change, it leans right. +* Continuing to advance the cursor (to the right) through the string causes the Logical Position column to _decrease_, and the Visual Position column to _increase_. * Once the cursor advances to between the `".` characters, the Logical Position column position is again 28, and leans forward. The Visual Position column position is now 61. -* Moving the caret right once more does not appear to visually advance the cursor. - However, the Logical Position and Visual Position column values are both 61, and both lean. +* Moving the caret right once more does not appear to visually advance the cursor. + However, the Logical Position and Visual Position column values are both 61, and both lean. * As the cursor advances to the right, both Logical and Visual column values increase. ```java @@ -167,12 +167,12 @@ Starting on the left end of the line, and using the arrow key to advance a line- } ``` -The apparent discontinuity in Logical Position is because the RTL portion of the string is treated (or counted) in the logical character order in which it would be written. +The apparent discontinuity in Logical Position is because the RTL portion of the string is treated (or counted) in the logical character order in which it would be written. The apparent continuity in Visual Position is because the RTL portion of the string is counted in the visual order in which it is displayed in the code. ### Caret Offset -The _Offset_ of a caret is a character count from the beginning of a `Document` to the caret position. -Caret offsets are always calculated in terms of Logical Position. +The _Offset_ of a caret is a character count from the beginning of a `Document` to the caret position. +Caret offsets are always calculated in terms of Logical Position. The caret Offset includes: * The first (0th) character in a document. * Whitespace characters, including newline and tabs. @@ -180,8 +180,8 @@ The caret Offset includes: (**Preferences \| Editor \| General \| Virtual Space**) * The character selected by the caret. -The example below demonstrates the Offset of a caret placed at the first character of Logical line one. -Note the Offset is 22, which is one greater than the number of visible characters on line zero, and the first character on line one. +The example below demonstrates the Offset of a caret placed at the first character of Logical line one. +Note the Offset is 22, which is one greater than the number of visible characters on line zero, and the first character on line one. This apparent discrepancy is actually correct because the Offset includes the newline character for line zero. ![Line 2 Caret Offset](img/caret_offset_l2.png){:width="800px"} @@ -198,14 +198,14 @@ public class EditorAreaIllustration extends AnAction { // Get access to the editor and caret model. final Editor editor = e.getRequiredData(CommonDataKeys.EDITOR); final CaretModel caretModel = editor.getCaretModel(); - + // Getting the primary caret ensures we get the correct one of a possible many. final Caret primaryCaret = caretModel.getPrimaryCaret(); // Get the caret information LogicalPosition logicalPos = primaryCaret.getLogicalPosition(); VisualPosition visualPos = primaryCaret.getVisualPosition(); int caretOffset = primaryCaret.getOffset(); - + // Build and display the caret report. String report = logicalPos.toString() + "\n" + visualPos.toString() + "\n" + "Offset: " + caretOffset; @@ -214,4 +214,3 @@ public class EditorAreaIllustration extends AnAction { } ``` - diff --git a/tutorials/editor_basics/editor_events.md b/tutorials/editor_basics/editor_events.md index 7e15d4edf..d62a2af30 100644 --- a/tutorials/editor_basics/editor_events.md +++ b/tutorials/editor_basics/editor_events.md @@ -3,30 +3,30 @@ title: 3. Handling Editor Events --- -The previous tutorial [Editor Coordinate Systems](coordinates_system.md) described working with caret coordinate systems in an editor window. -Caret position was discussed in terms of Logical Position, Visual Position, and Offset. -This tutorial introduces the Editor Action system, which handles actions activated by keystroke events in the editor. -Two classes from the [editor_basics](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/editor_basics) code sample are used to illustrate: -* Using an IntelliJ Platform [`EditorActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java) to manipulate a caret. -* Creating and registering a custom [`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java) to intercept keystrokes and change the document. +The previous tutorial [Editor Coordinate Systems](coordinates_system.md) described working with caret coordinate systems in an editor window. +Caret position was discussed in terms of Logical Position, Visual Position, and Offset. +This tutorial introduces the Editor Action system, which handles actions activated by keystroke events in the editor. +Two classes from the [editor_basics](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/editor_basics) code sample are used to illustrate: +* Using an IntelliJ Platform [`EditorActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java) to manipulate a caret. +* Creating and registering a custom [`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java) to intercept keystrokes and change the document. -The tutorial presents the following sections: +The tutorial presents the following sections: * bullet list {:toc} ## Using an IntelliJ Platform EditorActionHandler -In this portion of the tutorial, the [editor_basics](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/editor_basics) code sample is used to demonstrate cloning an existing caret. -A custom action class will use `EditorActionManager` to access a specific `EditorActionHandler` for caret cloning. -The `editor_basics` code sample adds an **Editor Add Caret** menu item to the editor context menu: +In this portion of the tutorial, the [editor_basics](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/editor_basics) code sample is used to demonstrate cloning an existing caret. +A custom action class will use `EditorActionManager` to access a specific `EditorActionHandler` for caret cloning. +The `editor_basics` code sample adds an **Editor Add Caret** menu item to the editor context menu: ![Editor Basics Menu](img/basics.png){:width="600px"} ### Creating the Menu Action Class -The source code for the Java action class is [EditorHandlerIllustration](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/editor_basics/src/main/java/org/intellij/sdk/editor/EditorHandlerIllustration.java), a subclass of `AnAction`. -For more information about creating action classes, see the [Actions Tutorial](/tutorials/action_system.md) which covers the topic in depth. +The source code for the Java action class is [EditorHandlerIllustration](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/editor_basics/src/main/java/org/intellij/sdk/editor/EditorHandlerIllustration.java), a subclass of `AnAction`. +For more information about creating action classes, see the [Actions Tutorial](/tutorials/action_system.md) which covers the topic in depth. -The `EditorHandlerIllustration` action is registered in the _editor_basic_ [`plugin.xml`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/editor_basics/src/main/resources/META-INF/plugin.xml) file. -Note that this action class is registered to appear on the Editor context menu. +The `EditorHandlerIllustration` action is registered in the _editor_basic_ [`plugin.xml`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/editor_basics/src/main/resources/META-INF/plugin.xml) file. +Note that this action class is registered to appear on the Editor context menu. ```xml @@ -41,13 +41,13 @@ Note that this action class is registered to appear on the Editor context menu. ``` ### Setting Visibility for the Action Menu Entry -Under what conditions should the `EditorHandlerIllustration` action be capable of cloning a caret? -Only if the following conditions are met in the `EditorHandlerIllustration.update()` method: -* A project is open, -* An editor is available, -* There is at least one caret active in the editor. +Under what conditions should the `EditorHandlerIllustration` action be capable of cloning a caret? +Only if the following conditions are met in the `EditorHandlerIllustration.update()` method: +* A project is open, +* An editor is available, +* There is at least one caret active in the editor. -After ensuring that `Project` and `Editor` objects are available, the `Editor` object is used to verify there is at least one caret: +After ensuring that `Project` and `Editor` objects are available, the `Editor` object is used to verify there is at least one caret: ```java public class EditorHandlerIllustration extends AnAction { @@ -68,13 +68,13 @@ public class EditorHandlerIllustration extends AnAction { ``` ### Acquiring the Correct EditorActionHandler -When the `EditorHandlerIllustration.actionPerformed()` method clones the caret, it should use the appropriate IntelliJ Platform [`EditorActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java). -An instance of [`EditorActionManager`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionManager.java) is required to obtain the correct `EditorActionHandler`. -The `EditorActionManager` class provides a static method to do this. +When the `EditorHandlerIllustration.actionPerformed()` method clones the caret, it should use the appropriate IntelliJ Platform [`EditorActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java). +An instance of [`EditorActionManager`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionManager.java) is required to obtain the correct `EditorActionHandler`. +The `EditorActionManager` class provides a static method to do this. -To request the correct `EditorActionHandler` from `EditorActionManager`, consult the [`IdeActions`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java) interface for the correct constant to pass into the `EditorActionManager.getActionHandler()` method. -For cloning a caret below the primary caret, the constant is `ACTION_EDITOR_CLONE_CARET_BELOW`. -Based on that constant, the `EditorActionManager` returns an instance of [`CloneCaretActionHandler`](upsource:///platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java), a subclass of `EditorActionHandler`. +To request the correct `EditorActionHandler` from `EditorActionManager`, consult the [`IdeActions`](upsource:///platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java) interface for the correct constant to pass into the `EditorActionManager.getActionHandler()` method. +For cloning a caret below the primary caret, the constant is `ACTION_EDITOR_CLONE_CARET_BELOW`. +Based on that constant, the `EditorActionManager` returns an instance of [`CloneCaretActionHandler`](upsource:///platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java), a subclass of `EditorActionHandler`. ```java // Snippet from EditorHandlerIllustration.actionPerformed() @@ -83,7 +83,7 @@ Based on that constant, the `EditorActionManager` returns an instance of [`Clone ``` ### Using an EditorActionHandler to Clone the Caret -To clone the caret requires only calling the `EditorActionHandler.execute()` method and passing in the appropriate context. +To clone the caret requires only calling the `EditorActionHandler.execute()` method and passing in the appropriate context. ```java public class EditorHandlerIllustration extends AnAction { @@ -99,21 +99,21 @@ public class EditorHandlerIllustration extends AnAction { ## Creating a Custom TypedActionHandler -The [`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java) interface is the basis for classes that handle keystroke events from the editor. -Custom implementations of the class are registered to handle editor keystroke events, and receive a callback for each keystroke. -The steps below explain how to use `TypedActionHandler` to customize the behavior of the editor when keystroke events are received. +The [`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java) interface is the basis for classes that handle keystroke events from the editor. +Custom implementations of the class are registered to handle editor keystroke events, and receive a callback for each keystroke. +The steps below explain how to use `TypedActionHandler` to customize the behavior of the editor when keystroke events are received. ### Implementing a Custom TypedActionHandler Class -First, a subclass such as `MyTypedHandler` is created based on [`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java). -The class overrides the method `TypedActionHandler.execute()`, which is the callback for editor keystroke events. +First, a subclass such as `MyTypedHandler` is created based on [`TypedActionHandler`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedActionHandler.java). +The class overrides the method `TypedActionHandler.execute()`, which is the callback for editor keystroke events. ### Implementing the Keystroke Event Handling Logic -Override the `TypedActionHandler.execute()` method in `MyTypedHandler` to implement the logic for handling keystroke events. -This method is called every time a key is pressed when the Editor Tool Window has focus. +Override the `TypedActionHandler.execute()` method in `MyTypedHandler` to implement the logic for handling keystroke events. +This method is called every time a key is pressed when the Editor Tool Window has focus. -In the following example, the `MyTypedHandler.execute()` method inserts "editor_basics\n" at the zero [caret Offset](coordinates_system.md#caret-offset) position when a keystroke event occurs. -As explained in [Working with Text](working_with_text.md#safely-replacing-selected-text-in-the-document), safe modifications to the document must be in the context of a write action. -So although a method on the `Document` interface does the `String` insertion, the write action ensures a stable context. +In the following example, the `MyTypedHandler.execute()` method inserts "editor_basics\n" at the zero [caret Offset](coordinates_system.md#caret-offset) position when a keystroke event occurs. +As explained in [Working with Text](working_with_text.md#safely-replacing-selected-text-in-the-document), safe modifications to the document must be in the context of a write action. +So although a method on the `Document` interface does the `String` insertion, the write action ensures a stable context. ```java class MyTypedHandler implements TypedActionHandler { @@ -128,11 +128,11 @@ class MyTypedHandler implements TypedActionHandler { ``` ### Registering a Custom TypedActionHandler -A custom implementation of `TypedActionHandler` must be registered to replace the existing typing handler to receive editor keystroke events. -The registration is done through the [`TypedAction`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java) class. +A custom implementation of `TypedActionHandler` must be registered to replace the existing typing handler to receive editor keystroke events. +The registration is done through the [`TypedAction`](upsource:///platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java) class. -As is shown in the snippet below, the `EditorActionManager` is used to get access to the `TypedAction` class. -The method `TypedAction.setupHandler()` is used to register the custom `MyTypedHandler` class: +As is shown in the snippet below, the `EditorActionManager` is used to get access to the `TypedAction` class. +The method `TypedAction.setupHandler()` is used to register the custom `MyTypedHandler` class: ```java public class EditorHandlerIllustration extends AnAction { @@ -144,7 +144,7 @@ public class EditorHandlerIllustration extends AnAction { } ``` -Placing the registration code in the `EditorHandlerIllustration` class is somewhat arbitrary in the sense that the registration of `MyTypedHandler` has nothing to do with the `EditorHandlerIllustration` class. -However, the `EditorHandlerIllustration` class is convenient because as an action it gets instantiated at application startup. -On instantiation, the `static` block of code in `EditorHandlerIllustration` gets evaluated. -In the `editor_basics` code sample any of the `AnAction` derived classes would work for registering `MyTypedHandler`. +Placing the registration code in the `EditorHandlerIllustration` class is somewhat arbitrary in the sense that the registration of `MyTypedHandler` has nothing to do with the `EditorHandlerIllustration` class. +However, the `EditorHandlerIllustration` class is convenient because as an action it gets instantiated at application startup. +On instantiation, the `static` block of code in `EditorHandlerIllustration` gets evaluated. +In the `editor_basics` code sample any of the `AnAction` derived classes would work for registering `MyTypedHandler`. diff --git a/tutorials/editor_basics/working_with_text.md b/tutorials/editor_basics/working_with_text.md index 671a3ca4f..89847d76e 100644 --- a/tutorials/editor_basics/working_with_text.md +++ b/tutorials/editor_basics/working_with_text.md @@ -3,26 +3,26 @@ title: Working with Text --- -This tutorial shows how to use actions to access a caret placed in a document open in an editor. -Using information about the caret, replace selected text in a document with a string. +This tutorial shows how to use actions to access a caret placed in a document open in an editor. +Using information about the caret, replace selected text in a document with a string. The tutorial presents the following sections: * bullet list {:toc} ## Introduction -The approach in this tutorial relies heavily on creating and registering actions. +The approach in this tutorial relies heavily on creating and registering actions. To review the fundamentals of creating and registering actions, refer to the [Actions Tutorial](/tutorials/action_system.md). -Multiple examples are used from the [editor_basics](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/editor_basics) plugin code sample from the IntelliJ Platform SDK. +Multiple examples are used from the [editor_basics](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/editor_basics) plugin code sample from the IntelliJ Platform SDK. It may be helpful to open that project in an IntelliJ Platform-based IDE, build the project, run it, select some text in the editor, and invoke the **Editor Replace Text** menu item on the editor context menu. ![Editor Basics Menu](img/basics.png){:width="600px"} ## Creating a New Menu Action -In this example, we access the `Editor` from an action. +In this example, we access the `Editor` from an action. The source code for the Java class in this example is [EditorIllustrationAction](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/editor_basics/src/main/java/org/intellij/sdk/editor/EditorIllustrationAction.java). -To register the action, we must add the corresponding elements to the `` section of the plugin configuration file [plugin.xml](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/editor_basics/src/main/resources/META-INF/plugin.xml). +To register the action, we must add the corresponding elements to the `` section of the plugin configuration file [plugin.xml](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/editor_basics/src/main/resources/META-INF/plugin.xml). For more information, refer to the [Registering Actions](/tutorials/action_system/working_with_custom_actions.md#registering-a-custom-action) section of the Actions Tutorial. The `EditorIllustrationAction` action is registered in the group `EditorPopupMenu` so it will be available from the context menu when focus is on the editor: @@ -37,7 +37,7 @@ The `EditorIllustrationAction` action is registered in the group `EditorPopupMen ``` ## Defining the Menu Action's Visibility -To determine conditions by which the action will be visible and available requires `EditorIllustrationAction` to override the `AnAction.update()` method. +To determine conditions by which the action will be visible and available requires `EditorIllustrationAction` to override the `AnAction.update()` method. For more information, refer to [Extending the Update Method](/tutorials/action_system/working_with_custom_actions.md#extending-the-update-method) section of the Actions Tutorial. To work with a selected part of the text, it's reasonable to make the menu action available only when the following requirements are met: @@ -48,7 +48,7 @@ To work with a selected part of the text, it's reasonable to make the menu actio Additional steps will show how to check these conditions through obtaining instances of `Project` and `Editor` objects, and how to show or hide the action's menu items based on them. ### Getting an Instance of the Active Editor from an Action Event -Using the [`AnActionEvent`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java) event passed into the `update` method, a reference to an instance of the `Editor` can be obtained by calling `getData(CommonDataKeys.EDITOR)`. +Using the [`AnActionEvent`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java) event passed into the `update` method, a reference to an instance of the `Editor` can be obtained by calling `getData(CommonDataKeys.EDITOR)`. Similarly, to obtain a project reference, we use the `getProject()` method. ```java @@ -62,15 +62,15 @@ public class EditorIllustrationAction extends AnAction { } ``` -**Note:** +**Note:** There are other ways to access an `Editor` instance: * If a [`DataContext`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/actionSystem/DataContext.java) object is available: `CommonDataKeys.EDITOR.getData(context);` * If only a `Project` object is available, use `FileEditorManager.getInstance(project).getSelectedTextEditor()` ### Obtaining a Caret Model and Selection After making sure a project is open, and an instance of the `Editor` is obtained, we need to check if any selection is available. -The [`SelectionModel`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/SelectionModel.java) interface is accessed from the `Editor` object. -Determining whether some text is selected is accomplished by calling the `SelectionModel.hasSelection()` method. +The [`SelectionModel`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/SelectionModel.java) interface is accessed from the `Editor` object. +Determining whether some text is selected is accomplished by calling the `SelectionModel.hasSelection()` method. Here's how the `EditorIllustrationAction.update(AnActionEvent e)` method should look: ```java @@ -80,17 +80,17 @@ public class EditorIllustrationAction extends AnAction { // Get required data keys final Project project = e.getProject(); final Editor editor = e.getData(CommonDataKeys.EDITOR); - + // Set visibility only in case of existing project and editor and if a selection exists - e.getPresentation().setEnabledAndVisible( project != null - && editor != null + e.getPresentation().setEnabledAndVisible( project != null + && editor != null && editor.getSelectionModel().hasSelection() ); } } ``` **Note:** -`Editor` also allows access to different models of text representation. +`Editor` also allows access to different models of text representation. The model classes are located in [editor](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor), and include: * [`CaretModel`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/CaretModel.java), * [`FoldingModel`](upsource:///platform/editor-ui-api/src/com/intellij/openapi/editor/FoldingModel.java), @@ -100,23 +100,23 @@ The model classes are located in [editor](upsource:///platform/editor-ui-api/src ## Safely Replacing Selected Text in the Document -Based on the evaluation of conditions by `EditorIllustrationAction.update()`, the `EditorIllustrationAction` action menu item is visible. -To make the menu item do something, the `EditorIllustrationAction` class must override the `AnAction.actionPerformed()` method. +Based on the evaluation of conditions by `EditorIllustrationAction.update()`, the `EditorIllustrationAction` action menu item is visible. +To make the menu item do something, the `EditorIllustrationAction` class must override the `AnAction.actionPerformed()` method. As explained below, this will require the `EditorIllustrationAction.actionPerformed()` method to: * Gain access to the document. * Get the character locations defining the selection. * Safely replace the contents of the selection. -Modifying the selected text requires an instance of the [`Document`](upsource:///platform/core-api/src/com/intellij/openapi/editor/Document.java) object, which is accessed from the `Editor` object. -The [Document](/basics/architectural_overview/documents.md) represents the contents of a text file loaded into memory and opened in an IntelliJ Platform-based IDE editor. +Modifying the selected text requires an instance of the [`Document`](upsource:///platform/core-api/src/com/intellij/openapi/editor/Document.java) object, which is accessed from the `Editor` object. +The [Document](/basics/architectural_overview/documents.md) represents the contents of a text file loaded into memory and opened in an IntelliJ Platform-based IDE editor. An instance of the `Document` will be used later when a text replacement is performed. -The text replacement will also require information about where the selection is in the document, which is provided by the primary `Caret` object, obtained from the `CaretModel`. +The text replacement will also require information about where the selection is in the document, which is provided by the primary `Caret` object, obtained from the `CaretModel`. Selection information is measured in terms of [Offset](coordinates_system.md#caret-offset), the count of characters from the beginning of the document to a caret location. -Text replacement could be done by calling the `Document` object's `replaceString()` method. -However, safely replacing the text requires the `Document` to be locked and any changes performed in a write action. -See the [Threading Issues](/basics/architectural_overview/general_threading_rules.md) section to learn more about synchronization issues and changes safety on the IntelliJ Platform. +Text replacement could be done by calling the `Document` object's `replaceString()` method. +However, safely replacing the text requires the `Document` to be locked and any changes performed in a write action. +See the [Threading Issues](/basics/architectural_overview/general_threading_rules.md) section to learn more about synchronization issues and changes safety on the IntelliJ Platform. This example changes the document within a [`WriteCommandAction`](upsource:///platform/core-api/src/com/intellij/openapi/command/WriteCommandAction.java). The complete `EditorIllustrationAction.actionPerformed()` method is shown below: @@ -131,22 +131,20 @@ public class EditorIllustrationAction extends AnAction { final Editor editor = e.getRequiredData(CommonDataKeys.EDITOR); final Project project = e.getRequiredData(CommonDataKeys.PROJECT); final Document document = editor.getDocument(); - + // Work off of the primary caret to get the selection info Caret primaryCaret = editor.getCaretModel().getPrimaryCaret(); int start = primaryCaret.getSelectionStart(); int end = primaryCaret.getSelectionEnd(); - + // Replace the selection with a fixed string. // Must do this document change in a write action context. WriteCommandAction.runWriteCommandAction(project, () -> document.replaceString(start, end, "editor_basics") ); - + // De-select the text range that was just replaced primaryCaret.removeSelection(); } } ``` - - diff --git a/tutorials/framework.md b/tutorials/framework.md index 6cc5b2f25..b95f544cc 100644 --- a/tutorials/framework.md +++ b/tutorials/framework.md @@ -15,9 +15,7 @@ public class DemoFramework extends FrameworkTypeEx { ``` ## 2. Registering Framework -The newly created framework class should be registered as an extension point by adding `com.intellij.framework.type` extension in -[`plugin.xml`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/framework_basics/src/main/resources/META-INF/plugin.xml) -configuration file: +The newly created framework class should be registered as an extension point by adding `com.intellij.framework.type` extension in [`plugin.xml`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/framework_basics/src/main/resources/META-INF/plugin.xml) configuration file: ```xml @@ -26,7 +24,7 @@ configuration file: ``` ## 3. Setting up Mandatory Attributes -The framework component should have a unique name passed as a string literal to the constructor. +The framework component should have a unique name passed as a string literal to the constructor. It is best if this is the FQN name of the class: ```java @@ -57,15 +55,15 @@ public class DemoFramework extends FrameworkTypeEx { ``` ## 4. Creating Provider for Enabling Framework Support -To make the framework set up available while executing the steps to create a project, the -`DemoFramework.createProvider()` method must be implemented to return an object of type [`FrameworkSupportInModuleConfigurable`](upsource:///java/idea-ui/src/com/intellij/framework/addSupport/FrameworkSupportInModuleConfigurable.java), which adds the framework to a module. +To make the framework set up available while executing the steps to create a project, the +`DemoFramework.createProvider()` method must be implemented to return an object of type [`FrameworkSupportInModuleConfigurable`](upsource:///java/idea-ui/src/com/intellij/framework/addSupport/FrameworkSupportInModuleConfigurable.java), which adds the framework to a module. In this example the framework is added to any [`ModuleType`](upsource:///platform/lang-api/src/com/intellij/openapi/module/ModuleType.java) without checking, which is usually not the case. ```java @NotNull @Override public FrameworkSupportInModuleProvider createProvider() { - return new FrameworkSupportInModuleProvider() { + return new FrameworkSupportInModuleProvider() { @NotNull @Override public FrameworkTypeEx getFrameworkType() { @@ -98,15 +96,6 @@ public FrameworkSupportInModuleProvider createProvider() { } ``` -After compiling and running the code sample above an extra option for configuring the newly created Demo custom framework should be available in the Project Wizard: +After compiling and running the code sample above an extra option for configuring the newly created Demo custom framework should be available in the Project Wizard: ![Custom Framework Support](framework/img/custom_framework.png) - - - - - - - - - diff --git a/tutorials/github_template.md b/tutorials/github_template.md index 432dc0a06..ffab31697 100644 --- a/tutorials/github_template.md +++ b/tutorials/github_template.md @@ -7,7 +7,9 @@ title: IntelliJ Platform Plugin Template The main goal of this template is to speed up the setup phase of plugin development for both new and experienced developers by preconfiguring the project scaffold and CI, linking to the proper documentation pages, and keeping everything organized. -GitHub Template allows you to create a new repository from the scaffold without having to copy and paste content, clone repositories, or clear the history manually. All you have to do is click the Use this template button on the GitHub project page. After that, the GitHub Actions workflow will be triggered to override or remove any template-specific configurations, such as the plugin name, current changelog, etc. +GitHub Template allows you to create a new repository from the scaffold without having to copy and paste content, clone repositories, or clear the history manually. +All you have to do is click the Use this template button on the GitHub project page. +After that, the GitHub Actions workflow will be triggered to override or remove any template-specific configurations, such as the plugin name, current changelog, etc. Once this is complete, the project is ready to be cloned to your local environment and opened with [IntelliJ IDEA][jb:download-ij]. diff --git a/tutorials/kotlin.md b/tutorials/kotlin.md index 0186d3bff..04854ef3e 100644 --- a/tutorials/kotlin.md +++ b/tutorials/kotlin.md @@ -5,22 +5,14 @@ title: Kotlin for Plugin Developers ## 1. Why Kotlin? -Using Kotlin to write plugins for the IntelliJ Platform is very similar to writing plugins in Java. Existing plugin -developers can get started by converting boilerplate Java classes to their Kotlin equivalents by using -the [J2K compiler](https://kotlinlang.org/docs/tutorials/mixing-java-kotlin-intellij.html#converting-an-existing-java-file-to-kotlin-with-j2k) -bundled with the IntelliJ Platform (versions 143.+), and developers can easily mix and match Kotlin classes with their -existing Java code. +Using Kotlin to write plugins for the IntelliJ Platform is very similar to writing plugins in Java. +Existing plugin developers can get started by converting boilerplate Java classes to their Kotlin equivalents by using the [J2K compiler](https://kotlinlang.org/docs/tutorials/mixing-java-kotlin-intellij.html#converting-an-existing-java-file-to-kotlin-with-j2k) bundled with the IntelliJ Platform (versions 143.+), and developers can easily mix and match Kotlin classes with their existing Java code. -In addition to [null safety](https://kotlinlang.org/docs/reference/null-safety.html) -and [type-safe builders](https://kotlinlang.org/docs/reference/type-safe-builders.html), the Kotlin language offers -a number of convenient features for plugin development, which make plugins easier to read and simpler to maintain. -Much like [Kotlin for Android](https://kotlinlang.org/docs/tutorials/kotlin-android.html), the IntelliJ Platform makes -extensive use of callbacks, which are easy to express as [lambdas](https://kotlinlang.org/docs/reference/lambdas.html) in Kotlin. +In addition to [null safety](https://kotlinlang.org/docs/reference/null-safety.html) and [type-safe builders](https://kotlinlang.org/docs/reference/type-safe-builders.html), the Kotlin language offers many convenient features for plugin development, which make plugins easier to read and simpler to maintain. +Much like [Kotlin for Android](https://kotlinlang.org/docs/tutorials/kotlin-android.html), the IntelliJ Platform makes extensive use of callbacks, which are easy to express as [lambdas](https://kotlinlang.org/docs/reference/lambdas.html) in Kotlin. -Likewise, it is easy to customize the behavior of internal classes in IntelliJ IDEA, with -[extensions](https://kotlinlang.org/docs/reference/extensions.html). For example, it is common practice to -[guard logging statements](https://www.slf4j.org/faq.html#logging_performance) to avoid the cost of parameter -construction, leading to the following ceremony when using the log: +Likewise, it is easy to customize the behavior of internal classes in IntelliJ IDEA, with [extensions](https://kotlinlang.org/docs/reference/extensions.html). +For example, it is common practice to [guard logging statements](https://www.slf4j.org/faq.html#logging_performance) to avoid the cost of parameter construction, leading to the following ceremony when using the log: ```java if (logger.isDebugEnabled()) { @@ -38,9 +30,9 @@ inline fun Logger.debug(lazyMessage: () -> String) { } ``` -Now we can directly write `logger.debug { "..." }` to receive all the benefits of lightweight logging, with none of the -verbosity. With practice, you will be able to recognize many idioms in the IntelliJ Platform that can be simplified with -Kotlin. To learn more about building IntelliJ Platform plugins with Kotlin, this tutorial will help you get started. +Now we can directly write `logger.debug { "..." }` to receive all the benefits of lightweight logging, with none of the verbosity. +With practice, you will be able to recognize many idioms in the IntelliJ Platform that can be simplified with Kotlin. +To learn more about building IntelliJ Platform plugins with Kotlin, this tutorial will help you get started. ## 2. Adding Kotlin Support @@ -52,11 +44,8 @@ For detailed instructions, please refer to the [Kotlin documentation](https://ko ## 3. Kotlin Gradle Plugin -For plugins already using the [Gradle Build System](build_system.md), or those that require precise control over -the Kotlin build process, we recommend using the -[kotlin-gradle-plugin](https://kotlinlang.org/docs/reference/using-gradle.html#configuring-dependencies). -This [Gradle plugin](https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-gradle-plugin-core) greatly -simplifies building Kotlin projects in a controlled and reproducible manner. +For plugins already using the [Gradle Build System](build_system.md), or those that require precise control over the Kotlin build process, we recommend using the [kotlin-gradle-plugin](https://kotlinlang.org/docs/reference/using-gradle.html#configuring-dependencies). +This [Gradle plugin](https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-gradle-plugin-core) greatly simplifies building Kotlin projects in a controlled and reproducible manner. Your `build.gradle` file may look like so: @@ -149,8 +138,8 @@ intellij { ## 4. UI in Kotlin -The best way to create user interfaces with Kotlin is to use a [type safe DSL](/user_interface_components/kotlin_ui_dsl.md) -for building forms. Using GUI designer with Kotlin is currently [not supported](https://youtrack.jetbrains.com/issue/KT-6660). +The best way to create user interfaces with Kotlin is to use a [type safe DSL](/user_interface_components/kotlin_ui_dsl.md) for building forms. +Using a GUI designer with Kotlin is currently [not supported](https://youtrack.jetbrains.com/issue/KT-6660). ## 5. Handling Kotlin Code @@ -159,13 +148,14 @@ Please refer to [Plugin Dependencies](/basics/plugin_structure/plugin_dependenci ## 6. Caution -Plugins *must* use Kotlin classes to implement declarations in the [plugin configuration file](/basics/plugin_structure/plugin_configuration_file.md). When registering an extension, the platform uses a dependency injection framework to instantiate these classes. For this reason, plugins *must not* use [Kotlin objects](https://kotlinlang.org/docs/reference/object-declarations.html) to implement any `plugin.xml` declarations. +Plugins *must* use Kotlin classes to implement declarations in the [plugin configuration file](/basics/plugin_structure/plugin_configuration_file.md). +When registering an extension, the platform uses a dependency injection framework to instantiate these classes. +For this reason, plugins *must not* use [Kotlin objects](https://kotlinlang.org/docs/reference/object-declarations.html) to implement any `plugin.xml` declarations. ## 7. Examples -There are a number of [open-source Kotlin projects](https://github.com/search?l=Kotlin&q=+intellij&ref=searchresults&type=Repositories) -built on the IntelliJ Platform. For a readily available source of up to date examples and applications of the Kotlin -language for building developer tools with the IntelliJ Platform, developers may look to these projects for inspiration: +There are many [open-source Kotlin projects](https://github.com/search?l=Kotlin&q=+intellij&ref=searchresults&type=Repositories) built on the IntelliJ Platform. +For a readily available source of up to date examples and applications of the Kotlin language for building developer tools with the IntelliJ Platform, developers may look to these projects for inspiration: * [IntelliJ-presentation-assistant](https://github.com/chashnikov/IntelliJ-presentation-assistant) * [Rust](https://github.com/intellij-rust/intellij-rust) diff --git a/tutorials/live_templates.md b/tutorials/live_templates.md index b2457fa02..ac2b98cf2 100644 --- a/tutorials/live_templates.md +++ b/tutorials/live_templates.md @@ -3,10 +3,11 @@ title: Live Templates --- -*Live Templates* are customizable rules that allow developers to abbreviate repetitive patterns of text in the editor. -When a user types the designated abbreviation followed by a configurable *expansion key* (usually `Tab`), the IDE transforms the preceding input sequence to its full-length output, and update the cursor position. +*Live Templates* are customizable rules that allow developers to abbreviate repetitive patterns of text in the editor. +When a user types the designated abbreviation followed by a configurable *expansion key* (usually `Tab`), the IDE transforms the preceding input sequence to its full-length output, and update the cursor position. -For example, consider a `for` loop. Typically, the end user would need to type `for (int i = 0; i < 10; i++) {}`. +For example, consider a `for` loop. +Typically, the end user would need to type `for (int i = 0; i < 10; i++) {}`. This pattern may be shortened to `fori` and the remaining contents will be expanded, leaving the following structure: ```java @@ -14,9 +15,9 @@ for (int i = [|]; i < []; i++) { [] } ``` - -As the user completes each section of the `for` loop and presses `Tab`, the cursor advances to the next position in the editor. -For more information about creating Custom Live Templates, refer to the [corresponding documentation](https://www.jetbrains.com/idea/help/creating-and-editing-live-templates.html). + +As the user completes each section of the `for` loop and presses `Tab`, the cursor advances to the next position in the editor. +For more information about creating Custom Live Templates, refer to the [corresponding documentation](https://www.jetbrains.com/idea/help/creating-and-editing-live-templates.html). These sections describe how to add Live Templates, and their associated building blocks, to plugins. * [Adding Live Templates to a Plugin](live_templates/template_support.md) diff --git a/tutorials/live_templates/new_macros.md b/tutorials/live_templates/new_macros.md index b1d3744cb..f875cdee6 100644 --- a/tutorials/live_templates/new_macros.md +++ b/tutorials/live_templates/new_macros.md @@ -6,7 +6,7 @@ title: Creating New Functions for Live Templates The [Predefined Functions](https://www.jetbrains.com/help/idea/template-variables.html?s=quick#predefined_functions) are the building blocks for creating [Parameterized Templates and Surround Templates](https://www.jetbrains.com/help/idea/using-live-templates.html?s=quick#live_templates_types). However, sometimes the Predefined Functions are not enough. -This tutorial illustrates how to add custom functions to an IntelliJ Platform plugin and make them available for use by Live Templates. +This tutorial illustrates how to add custom functions to an IntelliJ Platform plugin and make them available for use by Live Templates. As an example, a function is created to convert a selection to Title Case. Refer to the SDK code sample [`live_templates`](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/live_templates). @@ -18,7 +18,7 @@ Under the hood, the predefined functions for Live Templates are called _macros_. A new custom function for Live Templates is implemented in `TitleCaseMacro`, which extends [`MacroBase`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/macro/MacroBase.java). Three `TitleCaseMacro` methods are of particular interest: * The `TitleCaseMacro()` constructor passes the name and description of the macro to the parent constructor. -* The `isAcceptableInContext()` method tests whether the macro is available in the current context. +* The `isAcceptableInContext()` method tests whether the macro is available in the current context. The test relies on the [`MarkdownContext`](template_support.md#implement-templatecontexttype) object previously defined in the `live_templates` plugin. * The `calculateResult()` method gets invoked when the titleCase function is used in a Live Template. The text to be capitalized is retrieved from the Live Template and converted to Title Case. @@ -47,7 +47,7 @@ The argument to the `titleCase` function is `SELECTION`, which tells the Intelli ``` - + ## Register Extension Point Using the `com.intellij.liveTemplateMacro` extension point, register the implementation with the IntelliJ Platform. @@ -58,7 +58,7 @@ Using the `com.intellij.liveTemplateMacro` extension point, register the impleme ``` ## Check Plugin -Now verify the plugin is working correctly. +Now verify the plugin is working correctly. * Run the plugin in a Development Instance. * Create a new file `testing.md` and enter several words in lower case. * Highlight the text and enter ⌥⌘J to open the Select Template popup. @@ -67,6 +67,6 @@ Now verify the plugin is working correctly. ![Convert to title case](img/invoke_titleCase.png){:width="700px"} Test that the Live Template works by entering m or return. -The text will change to have each word capitalized: +The text will change to have each word capitalized: ![Converted to title case](img/applied_titleCase.png){:width="700px"} diff --git a/tutorials/live_templates/template_support.md b/tutorials/live_templates/template_support.md index 779315c23..2afba6890 100644 --- a/tutorials/live_templates/template_support.md +++ b/tutorials/live_templates/template_support.md @@ -3,7 +3,7 @@ title: Adding Live Templates to a Plugin --- -This tutorial illustrates how to add default Custom Live Templates to an IntelliJ Platform plugin, and assign valid contexts for these templates based on the surrounding code and file type. +This tutorial illustrates how to add default Custom Live Templates to an IntelliJ Platform plugin, and assign valid contexts for these templates based on the surrounding code and file type. In addition, the tutorial discusses how to export existing Live Templates, and bundle them within a plugin. Any Live Template that can be created and exported can be added to a plugin by following the Template Creation, Export, and Extension Point Registration processes. @@ -14,9 +14,9 @@ This tutorial uses the SDK code sample [`live_templates`](https://github.com/Jet ## Template Creation Get started by [creating a new Live Template](https://www.jetbrains.com/idea/help/creating-and-editing-live-templates.html) within the IntelliJ Platform-based IDE: -* Add a new Template Group, "Markdown" and create a new Live Template under this group. +* Add a new Template Group, "Markdown" and create a new Live Template under this group. * Assign the template the abbreviation "**{**". -* Assign the description "**SDK: New link reference**". +* Assign the description "**SDK: New link reference**". * Paste the following snippet into the *Template text* field: ```text @@ -31,15 +31,15 @@ There are many other [predefined functions](https://www.jetbrains.com/idea/help/ > **TIP** Consider iteratively testing the Live Template using the current editor and a markdown file to minimize debugging later. ## Export the Live Template -Once the Live Template produces the expected result, [export the Live Template](https://www.jetbrains.com/help/idea/sharing-live-templates.html). +Once the Live Template produces the expected result, [export the Live Template](https://www.jetbrains.com/help/idea/sharing-live-templates.html). The export produces a file called `Markdown.xml` with the following contents: ```xml - ``` -It is not always necessary to define your own `TemplateContextType`, as there are many existing template contexts already defined in the IntelliJ Platform. +It is not always necessary to define your own `TemplateContextType`, as there are many existing template contexts already defined in the IntelliJ Platform. Consider reusing one of the many existing template context types that inherit from `TemplateContextType` if you are augmenting language support to an existing area. -## Completing the Live Template Implementation +## Completing the Live Template Implementation Depending on the version of the IntelliJ Platform, different steps are used to complete the implementation of the feature. ### Versions 2020.1 and Later @@ -96,9 +96,9 @@ Now go to the [Check Plugin](#check-plugin) section to test the template. ### Versions 2019.3 and Earlier For older versions of the IntelliJ Platform follow this section to complete the implementation and register the extension points. Then proceed to the [Check Plugin](#check-plugin) section. - + #### Implement DefaultLiveTemplatesProvider -The `MarkdownTemplateProvider` tells the Platform where to find the Live Template settings file. +The `MarkdownTemplateProvider` tells the Platform where to find the Live Template settings file. Make sure to include the full path to the file, relative to the `src/main/resources` directory, excluding the file extension. ```java @@ -132,6 +132,6 @@ Using the `com.intellij.defaultLiveTemplatesProvider` and `com.intellij.liveTemp ``` ## Check Plugin -Now verify the plugin is working correctly. -Run the plugin in a Development Instance and verify there is a new entry under **Settings/Preferenes \| Live Templates \| Markdown \| \{ (SDK: New link reference)**. +Now verify the plugin is working correctly. +Run the plugin in a Development Instance and verify there is a new entry under **Settings/Preferenes \| Live Templates \| Markdown \| \{ (SDK: New link reference)**. Finally, create a new file `Test.md` and confirm that the Live Template works by entering a { character and then pressing Tab. diff --git a/tutorials/project_wizard.md b/tutorials/project_wizard.md index f7eed4c9a..b9778ea71 100644 --- a/tutorials/project_wizard.md +++ b/tutorials/project_wizard.md @@ -6,13 +6,12 @@ title: Project Wizard This set of tutorials shows how to manipulate the process of project creation. Configuring Project Wizard automatically allows you to do the following: - 1. [Adding New Steps to Project Wizard](project_wizard/adding_new_steps.md) 2. [Supporting Module Types](project_wizard/module_types.md) 3. Handling activities during project creation 4. Initial environment configuration -**Note:** +**Note:** Main utilities to configure a custom project wizard can be found in the package [lang-api.ide.util.projectWizard](upsource:///platform/lang-api/src/com/intellij/ide/util/projectWizard). diff --git a/tutorials/project_wizard/adding_new_steps.md b/tutorials/project_wizard/adding_new_steps.md index a5682040a..eec48a53e 100644 --- a/tutorials/project_wizard/adding_new_steps.md +++ b/tutorials/project_wizard/adding_new_steps.md @@ -8,12 +8,11 @@ This tutorial shows how to add an extra step to the Project Wizard to provide ad ## Pre-Requirements Create an empty plugin project. -See [Creating a Plugin Project](/tutorials/build_system.md) -to know how to do it. +See [Creating a Plugin Project](/tutorials/build_system.md) to know how to do it. ## 1. Register Module Builder -Project configuration settings depend on the project's module type. -Register a new `com.intellij.moduleBuilder` extension point in the `plugin.xml` configuration file. +Project configuration settings depend on the project's module type. +Register a new `com.intellij.moduleBuilder` extension point in the `plugin.xml` configuration file. ```xml @@ -36,7 +35,8 @@ public class DemoModuleWizardStep extends ModuleBuilder { ``` ## 3. Define Module Type -Set a module type for the extra wizard step to provide. In this example, choose an `EMPTY` module type. +Set a module type for the extra wizard step to provide. +In this example, choose an `EMPTY` module type. ```java public class DemoModuleWizardStep extends ModuleBuilder { @@ -62,7 +62,7 @@ public class DemoModuleWizardStep extends ModuleBuilder { } public ModuleType getModuleType() { - return ModuleType.EMPTY; + return ModuleType.EMPTY; } @Override @@ -82,13 +82,13 @@ public class DemoModuleWizardStep extends ModuleBuilder { } ``` -## 5. Checking UI Appearance +## 5. Checking UI Appearance After compiling and running the plugin, create a new project using a source-compiled instance of *IntelliJ IDEA*. ![New Project](img/empty_project.png) Choose an *Empty Module* type, click next, and get to the just added extra step. - -![Extra Step](img/extra_step.png) + +![Extra Step](img/extra_step.png) Modify and tune the UI component depending on requirements. diff --git a/tutorials/project_wizard/module_types.md b/tutorials/project_wizard/module_types.md index 5af64af70..3d6c8ce8f 100644 --- a/tutorials/project_wizard/module_types.md +++ b/tutorials/project_wizard/module_types.md @@ -3,7 +3,8 @@ title: Supporting Module Types --- -*IntelliJ Platform* provides a set of standard module types. However, an application might need a module of a type that isn't supported yet. +*IntelliJ Platform* provides a set of standard module types. +However, an application might need module of a type that isn't supported yet. This tutorial shows how to register a new module type and link it to the project creation procedure and the UI. ## Pre-Requirements @@ -49,4 +50,3 @@ Select **File \| New \| Module...** A new module type and its settings panel are available in the Project Wizard. ![New Module Type](module_types/img/new_module_type.png){:width="800px"} - diff --git a/tutorials/run_configurations.md b/tutorials/run_configurations.md index 2bd912658..31ede058f 100644 --- a/tutorials/run_configurations.md +++ b/tutorials/run_configurations.md @@ -5,10 +5,7 @@ title: Run Configurations These series of steps show how to register and implement a simple Run Configuration. Run Configurations are used to run internal and external processes from within *IntelliJ Platform* based products. -To get familiar with the concept of a Run Configuration refer -[Run/Debug Configuration](https://www.jetbrains.com/idea/help/run-debug-configuration.html) -section of -[IntelliJ IDEA Web Help](https://www.jetbrains.com/idea/help/intellij-idea.html) +To get familiar with the concept of a Run Configuration refer [Run/Debug Configuration](https://www.jetbrains.com/idea/help/run-debug-configuration.html) section of [IntelliJ IDEA Web Help](https://www.jetbrains.com/idea/help/intellij-idea.html) ## Pre-Requirements @@ -16,8 +13,7 @@ Create an empty plugin project as described in [Creating a Plugin Project](/basi ## 1. Register a New ConfigurationType -Add new `configurationType` extension to the -[plugin.xml](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/run_configuration/src/main/resources/META-INF/plugin.xml) +Add new `configurationType` extension to the [plugin.xml](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/run_configuration/src/main/resources/META-INF/plugin.xml) ```xml @@ -27,9 +23,7 @@ Add new `configurationType` extension to the ## 2. Implement ConfigurationType -Implement -[`ConfigurationType`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationType.java) -interface registered in the Step 1. +Implement [`ConfigurationType`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationType.java) interface registered in the Step 1. ```java public class DemoRunConfigurationType implements ConfigurationType { @@ -63,9 +57,7 @@ public class DemoRunConfigurationType implements ConfigurationType { ## 3. Implement a ConfigurationFactory -Implement a new -[`ConfigurationFactory`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) -through which custom run configurations will be created. +Implement a new [`ConfigurationFactory`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/ConfigurationFactory.java) through which custom run configurations will be created. ```java public class DemoConfigurationFactory extends ConfigurationFactory { @@ -92,12 +84,8 @@ public class DemoConfigurationFactory extends ConfigurationFactory { To make your changes visible from the UI, implement a new Run Configuration. -**Note:** In most of the cases you can derive a custom Run Configuration class from the -[`RunConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java). -If you need to implement specific settings externalization rules and I/O behaviour, -use -[`RunConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java) -interface. +**Note:** In most of the cases you can derive a custom Run Configuration class from the [`RunConfigurationBase`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java). +If you need to implement specific settings externalization rules and I/O behaviour, use [`RunConfiguration`](upsource:///platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java) interface. ```java public class DemoRunConfiguration extends RunConfigurationBase { @@ -128,9 +116,7 @@ public class DemoRunConfiguration extends RunConfigurationBase { Make sure _UI Designer_ plugin is [enabled](https://www.jetbrains.com/help/idea/managing-plugins.html). -Create a new -[UI form](https://www.jetbrains.com/help/idea/designing-gui-major-steps.html) -that defines, how an inner part of the new Run Configuration should look like. +Create a new [UI form](https://www.jetbrains.com/help/idea/designing-gui-major-steps.html) that defines, how an inner part of the new Run Configuration should look like. Default Run Configuration will be looking like this: @@ -170,10 +156,8 @@ public class DemoSettingsEditor extends SettingsEditor { ## 7. Compile and Run the Plugin -Refer to -[Running and Debugging a Plugin](/basics/getting_started/running_and_debugging_a_plugin.md). +Refer to [Running and Debugging a Plugin](/basics/getting_started/running_and_debugging_a_plugin.md). -After going through the steps described above you can create a custom Run Configuration -from your plugin. +After going through the steps described above you can create a custom Run Configuration from your plugin. ![New Run Configuration Type](run_configurations/img/new_run_configuration.png) diff --git a/tutorials/settings_tutorial.md b/tutorials/settings_tutorial.md index cfa14e23a..cef2b5060 100644 --- a/tutorials/settings_tutorial.md +++ b/tutorials/settings_tutorial.md @@ -4,19 +4,19 @@ title: Settings Tutorial ## Introduction -As discussed in the [_Settings_ Guide](/reference_guide/settings_guide.md), plugins can add Settings to IntelliJ Platform-based IDEs. -The IDE displays the Settings in response to a user choosing **Settings/Preferences**. +As discussed in the [_Settings_ Guide](/reference_guide/settings_guide.md), plugins can add Settings to IntelliJ Platform-based IDEs. +The IDE displays the Settings in response to a user choosing **Settings/Preferences**. Custom Settings are displayed and function just like those native to the IDE. * bullet list {:toc} ## Overview of a Custom Settings Implementation -Using the SDK code sample [`settings`](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/settings), this tutorial illustrates the steps to create custom Application-level Settings. -Many IntelliJ Platform Settings implementations use fewer classes, but the `settings` code sample factors the functionality into three classes for clarity : -* The [`AppSettingsConfigurable`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/settings/src/main/java/org/intellij/sdk/settings/AppSettingsConfigurable.java) is analogous to a Controller in the MVC model - it interacts with the other two Settings classes and the IntelliJ Platform, -* The [`AppSettingsState`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/settings/src/main/java/org/intellij/sdk/settings/AppSettingsState.java) is like a Model because it stores the Settings persistently, -* The [`AppSettingsComponent`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/settings/src/main/java/org/intellij/sdk/settings/AppSettingsComponent.java) is similar to a View because it displays and captures edits to the values of the Settings. +Using the SDK code sample [`settings`](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/settings), this tutorial illustrates the steps to create custom Application-level Settings. +Many IntelliJ Platform Settings implementations use fewer classes, but the `settings` code sample factors the functionality into three classes for clarity: +* The [`AppSettingsConfigurable`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/settings/src/main/java/org/intellij/sdk/settings/AppSettingsConfigurable.java) is analogous to a Controller in the MVC model - it interacts with the other two Settings classes and the IntelliJ Platform, +* The [`AppSettingsState`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/settings/src/main/java/org/intellij/sdk/settings/AppSettingsState.java) is like a Model because it stores the Settings persistently, +* The [`AppSettingsComponent`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/settings/src/main/java/org/intellij/sdk/settings/AppSettingsComponent.java) is similar to a View because it displays and captures edits to the values of the Settings. The structure of the implementation is the same for Project Settings, but there are minor differences in the [`Configurable` implementation](/reference_guide/settings_guide.md#constructors) and [Extension Point (EP) declaration](/reference_guide/settings_guide.md#declaring-project-settings). @@ -57,25 +57,25 @@ See [Implementing the State Class](/basics/persisting_state_of_components.md#imp #### AppSettingState Methods The fields are so limited and straightforward for this class that encapsulation is not used for simplicity. -All that's needed for functionality is to override the two methods called by the IntelliJ Platform when a new component state is loaded (`PersistentStateComponent.loadState()`), and when a state is saved (`PersistentStateComponent.getState()`). -See [`PersistentStateComponent`](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) for more information about these methods. +All that's needed for functionality is to override the two methods called by the IntelliJ Platform when a new component state is loaded (`PersistentStateComponent.loadState()`), and when a state is saved (`PersistentStateComponent.getState()`). +See [`PersistentStateComponent`](upsource:///platform/projectModel-api/src/com/intellij/openapi/components/PersistentStateComponent.java) for more information about these methods. One static convenience method has been added - `AppSettingState.getInstance()` - which allows `AppSettingsConfigurable` to easily acquire a reference to `AppSettingState`. ## The AppSettingsComponent Class The role of the [`AppSettingsComponent`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/settings/src/main/java/org/intellij/sdk/settings/AppSettingsComponent.java) is to provide a `JPanel` for the custom Settings to the IDE Settings Dialog. -The `AppSettingsComponent` has-a `JPanel`, and is responsible for its lifetime. -The `AppSettingsComponent` is instantiated by `AppSettingsConfigurable`. - +The `AppSettingsComponent` has-a `JPanel`, and is responsible for its lifetime. +The `AppSettingsComponent` is instantiated by `AppSettingsConfigurable`. + ### Creating the AppSettingsComponent Implementation -The `AppSettingsComponent` defines a `JPanel` containing a [`JBTextField`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBTextField.java) and a [`JBCheckBox`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBCheckBox.java) to hold and display the data that maps to the [data fields](#persistent-data-fields) of `AppSettingsState`: +The `AppSettingsComponent` defines a `JPanel` containing a [`JBTextField`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBTextField.java) and a [`JBCheckBox`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBCheckBox.java) to hold and display the data that maps to the [data fields](#persistent-data-fields) of `AppSettingsState`: ```java {% include /code_samples/settings/src/main/java/org/intellij/sdk/settings/AppSettingsComponent.java %} ``` #### AppSettingsComponent Methods -The constructor builds the `JPanel` using the convenient [`FormBuilder`](upsource:///platform/platform-api/src/com/intellij/util/ui/FormBuilder.java), and saves a reference to the `JPanel`. +The constructor builds the `JPanel` using the convenient [`FormBuilder`](upsource:///platform/platform-api/src/com/intellij/util/ui/FormBuilder.java), and saves a reference to the `JPanel`. The rest of the class are simple accessors and mutators to encapsulate the UI components used on the `JPanel`. @@ -83,8 +83,8 @@ The rest of the class are simple accessors and mutators to encapsulate the UI co The methods of [`AppSettingsConfigurable`](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/settings/src/main/java/org/intellij/sdk/settings/AppSettingsConfigurable.java) are called by the IntelliJ Platform, and `AppSettingsConfigurable` in turn interacts with `AppSettingsComponent` and `AppSettingState`. ### Declaring the AppSettingsConfigurable -As described in [Declaring Application Settings](/reference_guide/settings_guide.md#declaring-application-settings), the `com.intellij.applicationConfigurable` is used as the EP. -An explanation of this declaration can be found in [Declaring Application Settings](/reference_guide/settings_guide.md#declaring-application-settings): +As described in [Declaring Application Settings](/reference_guide/settings_guide.md#declaring-application-settings), the `com.intellij.applicationConfigurable` is used as the EP. +An explanation of this declaration can be found in [Declaring Application Settings](/reference_guide/settings_guide.md#declaring-application-settings): ```xml @@ -104,7 +104,7 @@ The class has one field to hold a reference to the `AppSettingsComponent`. ``` #### AppSettingsConfigurable Methods -All the methods in this class are overrides of the methods in the `Configurable` interface. +All the methods in this class are overrides of the methods in the `Configurable` interface. Readers are encouraged to review the Javadoc comments for the `Configurable` methods. Also review notes about [IntelliJ Platform Interactions](/reference_guide/settings_guide.md#intellij-platform-interactions-with-configurable) with `Configurable` methods. diff --git a/tutorials/tree_structure_view.md b/tutorials/tree_structure_view.md index b6d19ff7e..32275327e 100644 --- a/tutorials/tree_structure_view.md +++ b/tutorials/tree_structure_view.md @@ -3,24 +3,19 @@ title: Tree Structure View --- -This tutorial is meant to illustrate how the project tree structure view appearance can be modified programmatically. -If you need to know more about basic concepts of a project view in IntelliJ-based IDEs, please refer to -[Exploring The Project Structure](https://www.jetbrains.com/idea/help/exploring-the-project-structure.html#d164891e120) -of -[IntelliJ IDEA Web Help](https://www.jetbrains.com/idea/help/intellij-idea.html). +This tutorial is meant to illustrate how the project tree structure view appearance can be modified programmatically. +If you need to know more about basic concepts of a project view in IntelliJ-based IDEs, please refer to [Exploring The Project Structure](https://www.jetbrains.com/idea/help/exploring-the-project-structure.html#d164891e120) of [IntelliJ IDEA Web Help](https://www.jetbrains.com/idea/help/intellij-idea.html). -Series of step below show how to filter out and keep visible only text files and directories in the Project View Panel. +Series of step below show how to filter out and keep visible only text files and directories in the Project View Panel. ## Pre-Requirements Create an empty plugin project. -See -[Creating a Plugin Project](/tutorials/build_system/prerequisites.md). +See [Creating a Plugin Project](/tutorials/build_system/prerequisites.md). ## 1. Register Custom TreeStructure Provider -Add new *treeStructureProvider* extension to the -[plugin.xml](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/tree_structure_provider/src/main/resources/META-INF/plugin.xml) +Add new *treeStructureProvider* extension to the [plugin.xml](https://github.com/JetBrains/intellij-sdk-code-samples/blob/master/tree_structure_provider/src/main/resources/META-INF/plugin.xml) ```java @@ -30,7 +25,7 @@ Add new *treeStructureProvider* extension to the ## 2. Implement Custom TreeStructureProvider -To provide custom Structure View behaviour you need to implement TreeStructureProvider interface. +To provide custom Structure View behaviour you need to implement TreeStructureProvider interface. ```java public class TextOnlyTreeStructureProvider implements TreeStructureProvider { @@ -60,14 +55,11 @@ The example below shows how to filter out all the Project View nodes except thos ## 4. Compile and Run the Plugin Compile and run the code sample from this tutorial. -Refer to -[Running and Debugging a Plugin](/basics/getting_started/running_and_debugging_a_plugin.md). +Refer to [Running and Debugging a Plugin](/basics/getting_started/running_and_debugging_a_plugin.md). After going through the steps described above you can see only text files and directories belonging to a project in the Project View. ![Text Files](tree_structure_view/img/text_only.png) -Check out -[plugin source code](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/tree_structure_provider) -and build the project to see how TreeStructureView provider works in practice. +Check out [plugin source code](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/tree_structure_provider) and build the project to see how TreeStructureView provider works in practice. diff --git a/tutorials/writing_tests_for_plugins/completion_test.md b/tutorials/writing_tests_for_plugins/completion_test.md index d956c9b81..5d65df52a 100644 --- a/tutorials/writing_tests_for_plugins/completion_test.md +++ b/tutorials/writing_tests_for_plugins/completion_test.md @@ -60,4 +60,4 @@ The results are displayed in the **Run** Tool Window, and also written to the `s If the **Run** Tool Window displays the error *Test events were not received*, do the following: * In the **Gradle** Tool Window, drill down under `simple_language_plugin` to *Tasks*, *build*, *clean* task. * Run the *clean* task, which deletes the `simple_language_plugin/build/` directory. -* Retry the test. \ No newline at end of file +* Retry the test. diff --git a/tutorials/writing_tests_for_plugins/folding_test.md b/tutorials/writing_tests_for_plugins/folding_test.md index 3933be1f8..332a2ffef 100644 --- a/tutorials/writing_tests_for_plugins/folding_test.md +++ b/tutorials/writing_tests_for_plugins/folding_test.md @@ -17,7 +17,7 @@ This java file contains markup instructions for three different cases of code fo ## 7.2. Define a Test Add the `testFolding()` method to the `SimpleCodeInsightTest` class [previously defined](completion_test.md#define-a-test). -This test method reuses the `DefaultTestData.simple` properties file. +This test method reuses the `DefaultTestData.simple` properties file. ```java public void testFolding() { diff --git a/tutorials/writing_tests_for_plugins/parsing_test.md b/tutorials/writing_tests_for_plugins/parsing_test.md index 7f0f363b2..72bcf43e8 100644 --- a/tutorials/writing_tests_for_plugins/parsing_test.md +++ b/tutorials/writing_tests_for_plugins/parsing_test.md @@ -10,7 +10,7 @@ Before creating the parsing test, ensure the parser definition (`Simple.bnf`) in These additional lines facilitate testing incorrect keys. If the lines below are not present in `Simple.bnf`, replace the existing `property` definition with the lines below. -Don't forget to regenerate the parser after updating the file! +Don't forget to regenerate the parser after updating the file! Right-click on the `Simple.bnf` file and select **Generate Parser Code**. ```java diff --git a/tutorials/writing_tests_for_plugins/rename_test.md b/tutorials/writing_tests_for_plugins/rename_test.md index 3086d1402..d090cbdcf 100644 --- a/tutorials/writing_tests_for_plugins/rename_test.md +++ b/tutorials/writing_tests_for_plugins/rename_test.md @@ -33,7 +33,7 @@ Add the `testRename()` method to the `SimpleCodeInsightTest` class [previously d * Again, this method configures the test fixture by using the test files. * The fixture then renames the Simple Language element at the caret in `RenameTestData.java`. * It then compares the input and output property files, ignoring whitespace. - + ```java public void testRename() { myFixture.configureByFiles("RenameTestData.java", "RenameTestData.simple"); diff --git a/tutorials/writing_tests_for_plugins/tests_prerequisites.md b/tutorials/writing_tests_for_plugins/tests_prerequisites.md index 6d3da1311..57c4ca963 100644 --- a/tutorials/writing_tests_for_plugins/tests_prerequisites.md +++ b/tutorials/writing_tests_for_plugins/tests_prerequisites.md @@ -6,7 +6,7 @@ title: 1. Tests Prerequisites This page discusses the steps to configure a plugin project for creating tests. ## 1.1. Create a Folder for Tests -Open the plugin project, and under the `src` directory create a separate folder `test`. +Open the plugin project and create a separate folder named `test` under the `src` directory. Under `test`, create the `java` folder for test source code, and the folder `testData` for test data files and reimport the Gradle project. ```text @@ -24,7 +24,7 @@ Because some of the tests use Java files as test data, the tests need to mock up IntelliJ IDEA does everything automatically when the utility class [`LightJavaCodeInsightFixtureTestCase`](upsource:///java/testFramework/src/com/intellij/testFramework/fixtures/LightJavaCodeInsightFixtureTestCase.java) is used as the basis for the tests. The system properties are defined in the `build.gradle` file using the snippet shown below. -The `/path/to/community/` is set to the absolute path to the root directory of the local intellij-community source on the machine running the tests. +The `/path/to/community/` is set to the absolute path to the local intellij-community source's root directory on the machine running the tests. For example, on macOS the `path/to/community/` might be `/Users//Documents//` ```groovy diff --git a/user_interface_components/dialog_wrapper.md b/user_interface_components/dialog_wrapper.md index aa438c8ae..bd65b6ae6 100644 --- a/user_interface_components/dialog_wrapper.md +++ b/user_interface_components/dialog_wrapper.md @@ -5,60 +5,49 @@ title: Dialogs ## DialogWrapper -The -[`DialogWrapper`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java) -is the base class which is supposed to be used for all modal dialogs (and some non-modal dialogs) shown in *IntelliJ Platform*. +The [`DialogWrapper`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java) is the base class which is supposed to be used for all modal dialogs (and some non-modal dialogs) shown in *IntelliJ Platform*. It provides the following features: -* Button layout (platform-specific order of _OK_/_Cancel_ buttons, macOS-specific `Help` button) -* Context help -* Remembering the size of the dialog -* Non-modal validation (displaying an error message text when the data entered into the dialog is not valid) -* Keyboard shortcuts: - * Esc for closing the dialog - * Left/Right for switching between buttons - * Y/N for _Yes_/_No_ actions if they exist in the dialog -* Optional _Do not ask again_ checkbox +* Button layout (platform-specific order of _OK_/_Cancel_ buttons, macOS-specific `Help` button) +* Context help +* Remembering the size of the dialog +* Non-modal validation (displaying an error message text when the data entered into the dialog is not valid) +* Keyboard shortcuts: + * Esc for closing the dialog + * Left/Right for switching between buttons + * Y/N for _Yes_/_No_ actions if they exist in the dialog +* Optional _Do not ask again_ checkbox +When using the [`DialogWrapper`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java) class for a dialog, follow these steps: -When using the -[`DialogWrapper`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java) -class for a dialog, follow these steps: +* Call the base class constructor and provide either a project in the frame of which the dialog will be displayed, or a parent component for the dialog. +* Call the `init()` method from the constructor of the dialog class +* Call the `setTitle()` method to set the title for the dialog box +* Implement the `createCenterPanel()` method to return the component comprising the main contents of the dialog. -* Call the base class constructor and provide either a project in the frame of which the dialog will be displayed, or a parent component for the dialog. -* Call the `init()` method from the constructor of the dialog class -* Call the `setTitle()` method to set the title for the dialog box -* Implement the `createCenterPanel()` method to return the component comprising the main contents of the dialog. +* *Optional*: Override the `getPreferredFocusedComponent()` method and return the component that should be focused when the dialog is first displayed. +* *Optional*: Override the `getDimensionServiceKey()` method to return the identifier which will be used for persisting the dialog dimensions. +* *Optional*: Override the `getHelpId()` method to return the context help topic associated with the dialog. -* *Optional*: Override the `getPreferredFocusedComponent()` method and return the component that should be focused when the dialog is first displayed. -* *Optional*: Override the `getDimensionServiceKey()` method to return the identifier which will be used for persisting the dialog dimensions. -* *Optional*: Override the `getHelpId()` method to return the context help topic associated with the dialog. - -The -[`DialogWrapper`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java) -class is often used together with [GUI Designer forms](https://www.jetbrains.com/help/idea/gui-designer-basics.html). -In this case, bind a GUI Designer form to the class extending `DialogWrapper`, -bind the top-level panel of the form to a field and return that field from the `createCenterPanel()` method. +The [`DialogWrapper`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java) class is often used together with [GUI Designer forms](https://www.jetbrains.com/help/idea/gui-designer-basics.html). +In this case, bind a GUI Designer form to the class extending `DialogWrapper`, bind the top-level panel of the form to a field and return that field from the `createCenterPanel()` method. When using Kotlin, use [Kotlin UI DSL](kotlin_ui_dsl.md) to provide the dialog's contents. - + > **TIP** Existing dialogs can be inspected at runtime using [UI Inspector](/reference_guide/internal_actions/internal_ui_inspector.md), e.g., to locate the underlying implementation of UI components. -To display the dialog, call the `show()` method and then use the `getExitCode()` method to check how the dialog was closed. The `showAndGet()` method can be used to combine these two calls. +To display the dialog, call the `show()` method and then use the `getExitCode()` method to check how the dialog was closed. +The `showAndGet()` method can be used to combine these two calls. To customize the buttons displayed in the dialog (replacing the standard _OK_/_Cancel_/_Help_ set of buttons), override either the `createActions()` or `createLeftActions()` methods. Both of these methods return an array of Swing Action objects. -If a button closes the dialog, use -[`DialogWrapperExitAction`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java) -as the base class for the action. +If a button closes the dialog, use [`DialogWrapperExitAction`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java) as the base class for the action. Use `action.putValue(DialogWrapper.DEFAULT_ACTION, true)` to set the default button. To validate the data entered into the dialog, override the `doValidate()` method. The method will be called automatically by timer. If the currently entered data is valid, return `null`. -Otherwise, return a -[`ValidationInfo`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/ValidationInfo.java) -object which encapsulates an error message, and an optional component associated with the invalid data. +Otherwise, return a [`ValidationInfo`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/ValidationInfo.java) object which encapsulates an error message, and an optional component associated with the invalid data. When specifying a component, an error icon will be displayed next to it, and it will be focused when the user tries to invoke the _OK_ action. ## Example diff --git a/user_interface_components/editor_components.md b/user_interface_components/editor_components.md index c544cdb9c..14f94ba63 100644 --- a/user_interface_components/editor_components.md +++ b/user_interface_components/editor_components.md @@ -5,34 +5,24 @@ title: Editor Components ## EditorTextField -Compared to -[Swing `JTextArea`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JTextArea.html), the -*IntelliJ Platform's* editor component has a ton of advantages: syntax highlighting support, code completion, code folding and much more. +Compared to [Swing `JTextArea`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JTextArea.html), the *IntelliJ Platform's* editor component has a ton of advantages: syntax highlighting support, code completion, code folding and much more. Editors are normally displayed in editor tabs, but they can be embedded in dialogs or tool windows, too. -This is enabled by the -[`EditorTextField`](upsource:///platform/platform-impl/src/com/intellij/ui/EditorTextField.java) -component. +This is enabled by the [`EditorTextField`](upsource:///platform/platform-impl/src/com/intellij/ui/EditorTextField.java) component. The following attributes can be specified: -* The file type according to which the text in the text field is parsed; -* Whether the text field is read-only or editable; -* Whether the text field is single-line or multiline. - +* The file type according to which the text in the text field is parsed; +* Whether the text field is read-only or editable; +* Whether the text field is single-line or multiline. + Further customizations are possible by subclassing and overriding `createEditor()`. A common use case for `EditorTextField` is entering the name of a Java class or package. This can be accomplished with the following steps: -* Use - [`JavaCodeFragmentFactory.getInstance().createReferenceCodeFragment()`](upsource:///java/java-psi-api/src/com/intellij/psi/JavaCodeFragmentFactory.java) - to create a code fragment representing the class or package name; -* Call - [`PsiDocumentManager.getInstance().getDocument()`](upsource:///platform/core-api/src/com/intellij/psi/PsiDocumentManager.java) - to get the document corresponding to the code fragment; -* Pass the returned document to the - [`EditorTextField`](upsource:///platform/platform-impl/src/com/intellij/ui/EditorTextField.java) - constructor or its `setDocument()` method. +* Use [`JavaCodeFragmentFactory.getInstance().createReferenceCodeFragment()`](upsource:///java/java-psi-api/src/com/intellij/psi/JavaCodeFragmentFactory.java) to create a code fragment representing the class or package name; +* Call [`PsiDocumentManager.getInstance().getDocument()`](upsource:///platform/core-api/src/com/intellij/psi/PsiDocumentManager.java) to get the document corresponding to the code fragment; +* Pass the returned document to the [`EditorTextField`](upsource:///platform/platform-impl/src/com/intellij/ui/EditorTextField.java) constructor or its `setDocument()` method. E.g.: @@ -48,8 +38,12 @@ Document document = PsiDocumentManager.getInstance(editor.getProject()).getDocum EditorTextField myInput = new EditorTextField(document, editor.getProject(), JavaFileType.INSTANCE); ``` -**TIPS**: +**TIPS**: -* When creating more than one field two separate documents are needed. This is accomplished by using separate instances of `PsiExpressionCodeFragment`. -* `setText()` no longer works for the input field. However, `createExpressionCodeFragment()` accepts the text for the field as an argument. The empty string can be replaced and create a new document in lieu of `setText()`. -* Instances of `JTextField` in the GUI builder can be replaced with a custom replacement component using the right click in your IDE. Make sure to use "Custom Create", so the initialization code works properly. +* When creating more than one field two separate documents are needed. + This is accomplished by using separate instances of `PsiExpressionCodeFragment`. +* `setText()` no longer works for the input field. + However, `createExpressionCodeFragment()` accepts the text for the field as an argument. + The empty string can be replaced and create a new document in lieu of `setText()`. +* Instances of `JTextField` in the GUI builder can be replaced with a custom replacement component using the right click in your IDE. + Make sure to use "Custom Create", so the initialization code works properly. diff --git a/user_interface_components/file_and_class_choosers.md b/user_interface_components/file_and_class_choosers.md index 4b4560daa..cddb38900 100644 --- a/user_interface_components/file_and_class_choosers.md +++ b/user_interface_components/file_and_class_choosers.md @@ -6,16 +6,12 @@ title: File and Class Choosers ## File Choosers ### Via Dialog -To let a user choose a file, directory or multiple files, use the -[`FileChooser.chooseFiles()`](upsource:///platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java) -method. +To let a user choose a file, directory or multiple files, use the [`FileChooser.chooseFiles()`](upsource:///platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java) method. This method has multiple overloads. The best method to use is the one which returns void and takes a callback receiving the list of selected files as a parameter. This is the only overload which will display a native file open dialog on macOS. -The -[`FileChooserDescriptor`](upsource:///platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java) -class allows you to control which files can be selected. +The [`FileChooserDescriptor`](upsource:///platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java) class allows you to control which files can be selected. The constructor parameters specify whether files and/or directories can be selected, and whether multiple selection is allowed (see [FileChooserDescriptorFactory](upsource:///platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java) for common variants). For more fine-grained control over the allowed selection, you can overload the `isFileSelectable()` method. @@ -25,9 +21,7 @@ Note that the native macOS file chooser does not support most of the customizati ### Via Textfield A very common way of using file choosers is to use a text field for entering the path with an ellipsis button ("...") for showing the file chooser. -To create such a control, use the -[`TextFieldWithBrowseButton`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/TextFieldWithBrowseButton.java) -component and call the `addBrowseFolderListener()` method on it to set up the file chooser. +To create such a control, use the [`TextFieldWithBrowseButton`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/TextFieldWithBrowseButton.java) component and call the `addBrowseFolderListener()` method on it to set up the file chooser. As an added bonus, this will enable filename completion when entering paths in the text box. ### Via Tree @@ -45,12 +39,7 @@ To show the dialog, call `showDialog()` on the chooser returned from `createFile ## Class and Package Choosers -If you want to offer the user a possibility to select a Java class, you can use the -[`TreeClassChooserFactory`](upsource:///java/openapi/src/com/intellij/ide/util/TreeClassChooserFactory.java) -class. +If you want to offer the user a possibility to select a Java class, you can use the [`TreeClassChooserFactory`](upsource:///java/openapi/src/com/intellij/ide/util/TreeClassChooserFactory.java) class. Its different methods allow you to specify the scope from which the classes are taken, to restrict the choice to descendants of a specific class or implementations of an interface, and to include or exclude inner classes from the list. -For choosing a Java package, you can use the -[`PackageChooserDialog`](upsource:///java/java-impl/src/com/intellij/ide/util/PackageChooserDialog.java) -class. - +For choosing a Java package, you can use the [`PackageChooserDialog`](upsource:///java/java-impl/src/com/intellij/ide/util/PackageChooserDialog.java) class. diff --git a/user_interface_components/kotlin_ui_dsl.md b/user_interface_components/kotlin_ui_dsl.md index 5dc0c2cac..5b7209d04 100644 --- a/user_interface_components/kotlin_ui_dsl.md +++ b/user_interface_components/kotlin_ui_dsl.md @@ -5,7 +5,8 @@ title: Kotlin UI DSL > **WARNING** Please note the Kotlin UI DSL is in active development and [breaking changes](../reference_guide/api_changes_list.md) can occur between major releases. -> **NOTE** This document covers the Kotlin UI DSL in IntelliJ Platform 2019.2. A lot of the features described in this document are not available for plugins targeting earlier versions. +> **NOTE** This document covers the Kotlin UI DSL in IntelliJ Platform 2019.2. +> A lot of the features described in this document are not available for plugins targeting earlier versions. ## Layout Structure @@ -29,7 +30,8 @@ The label for the row can be specified as a parameter for the `row` method: row("Parameters") { ... } ``` -Rows can be nested. Components in a nested row block are considered to be subordinate to the containing row and are indented accordingly. +Rows can be nested. +Components in a nested row block are considered to be subordinate to the containing row and are indented accordingly. ```kotlin row { @@ -70,12 +72,15 @@ row { ## Adding Components -There are two ways to add child components. The recommended way is to use factory methods `label`, `button`, `radioButton`, `hint`, `link`, etc. It allows you to create consistent UI and reuse common patterns. +There are two ways to add child components. +The recommended way is to use factory methods `label`, `button`, `radioButton`, `hint`, `link`, etc. +It allows you to create consistent UI and reuse common patterns. ```kotlin note("""Do not have an account? Sign Up""", span, wrap) ``` -These methods also support **property bindings**, allowing you to automatically load the value displayed in the component from a property and to store it back. The easiest way to do that is to pass a reference to a Kotlin bound property: +These methods also support **property bindings**, allowing you to automatically load the value displayed in the component from a property and to store it back. +The easiest way to do that is to pass a reference to a Kotlin bound property: ```kotlin checkBox("Show tabs in single row", uiSettings::scrollTabLayoutInEditor) @@ -118,8 +123,9 @@ See examples above. ### Radio Buttons -Radio button groups are created using the `buttonGroup` block. There are two ways to use it. If the selected radio button corresponds to a specific value of a single -property, pass the property binding to the `buttonGroup` method and the specific values to `radioButton` functions: +Radio button groups are created using the `buttonGroup` block. +There are two ways to use it. +If the selected radio button corresponds to a specific value of a single property, pass the property binding to the `buttonGroup` method and the specific values to `radioButton` functions: ```kotlin buttonGroup(mySettings::providerType) { @@ -226,14 +232,15 @@ checkBox(message("checkbox.smart.tab.reuse"), ## Integrating Panels with Property Bindings -A panel returned by the `panel` method is an instance of [`DialogPanel`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogPanel.kt). This base class supports the standard `apply`, `reset`, and `isModified` methods. +A panel returned by the `panel` method is an instance of [`DialogPanel`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogPanel.kt). +This base class supports the standard `apply`, `reset`, and `isModified` methods. ### Dialogs -If you're using a [`DialogPanel`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogPanel.kt) as the main panel of a `DialogWrapper`, the `apply` method will be automatically called when the dialog is closed with the OK action. The other methods are unused in this case. +If you're using a [`DialogPanel`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogPanel.kt) as the main panel of a `DialogWrapper`, the `apply` method will be automatically called when the dialog is closed with the OK action. +The other methods are unused in this case. -Use the `focused` method to specify which control should be focused when -the dialog is initialized: +Use the `focused` method to specify which control should be focused when the dialog is initialized: ```kotlin return panel { @@ -245,11 +252,13 @@ return panel { ### Configurables -If you're using the UI DSL to implement a [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java), use [`BoundConfigurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/BoundConfigurable.kt) as the base class. In this case, the `Configurable` methods will be automatically delegated to the panel. +If you're using the UI DSL to implement a [`Configurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/Configurable.java), use [`BoundConfigurable`](upsource:///platform/platform-api/src/com/intellij/openapi/options/BoundConfigurable.kt) as the base class. +In this case, the `Configurable` methods will be automatically delegated to the panel. ## Enabling and Disabling Controls -Use the `enableIf` method to bind the enabled state of a control to the values entered in other controls. The parameter of the method is a **predicate**. +Use the `enableIf` method to bind the enabled state of a control to the values entered in other controls. +The parameter of the method is a **predicate**. ```kotlin checkBox("Show tabs in single row", uiSettings::scrollTabLayoutInEditor) @@ -257,9 +266,9 @@ checkBox("Show tabs in single row", uiSettings::scrollTabLayoutInEditor) ``` The available predicates are: - * `selected` to check the selected state of a checkbox or radio button - * `selectedValueIs` and `selectedValueMatches` to check the selected item in a combobox. - +* `selected` to check the selected state of a checkbox or radio button +* `selectedValueIs` and `selectedValueMatches` to check the selected item in a combobox. + Predicates can be combined with `and` and `or` infix functions: ```kotlin diff --git a/user_interface_components/lists_and_trees.md b/user_interface_components/lists_and_trees.md index ae555a02d..4c2c469f9 100644 --- a/user_interface_components/lists_and_trees.md +++ b/user_interface_components/lists_and_trees.md @@ -5,88 +5,48 @@ title: List and Tree Controls ### JBList and Tree -Whenever you would normally use a standard -[Swing `JList`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JList.html) -component, it's recommended to use the -[`JBList`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBList.java) -class as drop-in replacement. -[`JBList`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBList.java) -supports the following additional features on top of -[`JList`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JList.html): +Whenever you would normally use a standard [Swing `JList`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JList.html) component, it's recommended to use the [`JBList`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBList.java) class as drop-in replacement. [`JBList`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBList.java) supports the following additional features on top of [`JList`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JList.html): -* Drawing a tooltip with complete text of an item if the item doesn't fit into the list box width. +* Drawing a tooltip with complete text of an item if the item doesn't fit into the list box width. +* Drawing a gray text message in the middle of the list box when it contains no items. + The text can be customized by calling `getEmptyText().setText()`. +* Drawing a busy icon in the top right corner of the list box to indicate that a background operation is being performed. + This can be enabled by calling `setPaintBusy()`. -* Drawing a gray text message in the middle of the list box when it contains no items. - The text can be customized by calling `getEmptyText().setText()`. - -* Drawing a busy icon in the top right corner of the list box to indicate that a background operation is being performed. - This can be enabled by calling `setPaintBusy()`. - -Similarly, the -[`Tree`](upsource:///platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java) -class provides a replacement for the standard -[`JTree`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JTree.html) -class. -In addition to the features of -[`JBList`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBList.java), -it supports wide selection painting (Mac style) and auto-scroll on drag & drop. +Similarly, the [`Tree`](upsource:///platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java) class provides a replacement for the standard [`JTree`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JTree.html) class. +In addition to the features of [`JBList`](upsource:///platform/platform-api/src/com/intellij/ui/components/JBList.java), it supports wide selection painting (Mac style) and auto-scroll on drag & drop. ### ColoredListCellRenderer and ColoredTreeCellRenderer -When you need to customize the presentation of items in a list box or a tree, it's recommended to use the -[`ColoredListCellRenderer`](upsource:///platform/platform-api/src/com/intellij/ui/ColoredListCellRenderer.java) -or -[`ColoredTreeCellRenderer`](upsource:///platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java) -classes as the cell renderer. +When you need to customize the presentation of items in a list box or a tree, it's recommended to use the [`ColoredListCellRenderer`](upsource:///platform/platform-api/src/com/intellij/ui/ColoredListCellRenderer.java) or [`ColoredTreeCellRenderer`](upsource:///platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java) classes as the cell renderer. These classes allow you to compose the presentation out of multiple text fragments with different attributes by calling `append()` and to set an optional icon for the item by calling `setIcon`. The renderer automatically takes care of setting the correct text color for selected items and of many other platform-specific rendering details. ### ListSpeedSearch and TreeSpeedSearch -To facilitate keyboard-based selection of items in a list box or a tree, you can install a speed search handler on it using the -[`ListSpeedSearch`](upsource:///platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java) -and -[`TreeSpeedSearch`](upsource:///platform/platform-impl/src/com/intellij/ui/TreeSpeedSearch.java). +To facilitate keyboard-based selection of items in a list box or a tree, you can install a speed search handler on it using the [`ListSpeedSearch`](upsource:///platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java) and [`TreeSpeedSearch`](upsource:///platform/platform-impl/src/com/intellij/ui/TreeSpeedSearch.java). This can be done simply by calling `new ListSpeedSearch(list)` or `new TreeSpeedSearch(tree)`. If you need to customize the text which is used to locate the element, you can override the `getElementText()` method. Alternatively, you can pass a function to convert items to strings. -A function needs to be passed as `elementTextDelegate` to the -[`ListSpeedSearch`](upsource:///platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java) -constructor or as `toString` to the -[`TreeSpeedSearch`](upsource:///platform/platform-impl/src/com/intellij/ui/TreeSpeedSearch.java) -constructor. +A function needs to be passed as `elementTextDelegate` to the [`ListSpeedSearch`](upsource:///platform/platform-impl/src/com/intellij/ui/ListSpeedSearch.java) constructor or as `toString` to the [`TreeSpeedSearch`](upsource:///platform/platform-impl/src/com/intellij/ui/TreeSpeedSearch.java) constructor. ### ToolbarDecorator A very common task in plugin development is showing a list or a tree where the user is allowed to add, remove, edit or reorder the items. -The implementation of this task is greatly facilitated by the -[`ToolbarDecorator`](upsource:///platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java) -class. +The implementation of this task is greatly facilitated by the [`ToolbarDecorator`](upsource:///platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java) class. This class provides a toolbar with actions on items and automatically enables drag & drop reordering of items in list boxes if supported by the underlying list model. The position of the toolbar above or below the list depends on the platform under which the IDE is running. To use a toolbar decorator: -* If you need to support removing and reordering of items in a list box, make sure the model of your list implements the - [`EditableModel`](upsource:///platform/util/ui/src/com/intellij/util/ui/EditableModel.java) - interface. - [`CollectionListModel`](upsource:///platform/util/ui/src/com/intellij/ui/CollectionListModel.java) - is a handy model class that implements this interface. - -* Call - [`ToolbarDecorator.createDecorator()`](upsource:///platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java) - to create a decorator instance. - -* If you need to support adding and/or removing items, call `setAddAction()` and/or `setRemoveAction()`. - -* If you need other buttons in additional to the standard ones, call `addExtraAction()` or `setActionGroup()`. - -* Call `createPanel()` and add the component it returns to your panel. +* If you need to support removing and reordering of items in a list box, make sure the model of your list implements the [`EditableModel`](upsource:///platform/util/ui/src/com/intellij/util/ui/EditableModel.java) interface. + [`CollectionListModel`](upsource:///platform/util/ui/src/com/intellij/ui/CollectionListModel.java) is a handy model class that implements this interface. +* Call [`ToolbarDecorator.createDecorator()`](upsource:///platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java) to create a decorator instance. +* If you need to support adding and/or removing items, call `setAddAction()` and/or `setRemoveAction()`. +* If you need other buttons in additional to the standard ones, call `addExtraAction()` or `setActionGroup()`. +* Call `createPanel()` and add the component it returns to your panel. - - - diff --git a/user_interface_components/misc_swing_components.md b/user_interface_components/misc_swing_components.md index cf4f17a15..8fa8062f5 100644 --- a/user_interface_components/misc_swing_components.md +++ b/user_interface_components/misc_swing_components.md @@ -5,9 +5,7 @@ title: Miscellaneous Swing Components ### Messages -The -[`Messages`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/Messages.java) -class provides a way to show simple message boxes, input dialogs (modal dialogs with a text field), and chooser dialogs (modal dialogs with a combo box). +The [`Messages`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/Messages.java) class provides a way to show simple message boxes, input dialogs (modal dialogs with a text field), and chooser dialogs (modal dialogs with a combo box). The function of different methods of the class should be clear from their names. When running on macOS, the message boxes shown by the `Messages` class use the native UI. @@ -18,11 +16,7 @@ Please refer to the [Notifications](notifications.md) topic for more information ### JBSplitter -The -[`JBSplitter`](upsource:///platform/platform-api/src/com/intellij/ui/JBSplitter.java) -class is JetBrains' replacement for the standard -[`JSplitPane`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JSplitPane.html) -class. +The [`JBSplitter`](upsource:///platform/platform-api/src/com/intellij/ui/JBSplitter.java) class is JetBrains' replacement for the standard [`JSplitPane`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JSplitPane.html) class. Unlike some other JetBrains-enhanced Swing components, it's not a drop-in replacement and has a different API. However, to achieve a consistent user experience, it's recommended to use `JBSplitter` instead of the standard `JSplitPane`. @@ -33,11 +27,8 @@ To enable it, call the `setSplitterProportionKey()` method and pass the ID under ### JBTabs -The -[`JBTabs`](upsource:///platform/platform-api/src/com/intellij/ui/tabs/JBTabs.java) -class is JetBrains' implementation of the tab control, used for editor tabs and a few other components. +The [`JBTabs`](upsource:///platform/platform-api/src/com/intellij/ui/tabs/JBTabs.java) class is JetBrains' implementation of the tab control, used for editor tabs and a few other components. It has a significantly different look & feel compared to the standard Swing tabs, and looks less native on the macOS platform, so it's up to the developer to choose which tab control would be more appropriate. - ### Toolbars -See [Building UI from Actions](/basics/action_system.md#building-ui-from-actions) on how to create `AnAction`-based toolbars. \ No newline at end of file +See [Building UI from Actions](/basics/action_system.md#building-ui-from-actions) on how to create `AnAction`-based toolbars. diff --git a/user_interface_components/notifications.md b/user_interface_components/notifications.md index cc3eca77b..310d86ee6 100644 --- a/user_interface_components/notifications.md +++ b/user_interface_components/notifications.md @@ -8,56 +8,40 @@ As a replacement, the *IntelliJ Platform* provides multiple non-modal notificati ### Dialogs -When working in dialog, instead of checking the validity of the input when the _OK_ button is pressed and notifying the user about invalid data with a modal dialog, the recommended approach is to use -[`DialogWrapper.doValidate()`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java), -which was described previously. +When working in dialog, instead of checking the validity of the input when the _OK_ button is pressed and notifying the user about invalid data with a modal dialog, the recommended approach is to use [`DialogWrapper.doValidate()`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java), which was described previously. ### Editor Hints -For actions invoked from the editor (such as refactorings, navigation actions and different code insight features), the best way to notify the user about the inability to perform an action is to use the -[`HintManager`](upsource:///platform/platform-api/src/com/intellij/codeInsight/hint/HintManager.java) -class. +For actions invoked from the editor (such as refactorings, navigation actions and different code insight features), the best way to notify the user about the inability to perform an action is to use the [`HintManager`](upsource:///platform/platform-api/src/com/intellij/codeInsight/hint/HintManager.java) class. Its method `showErrorHint()` displays a floating popup above the editor which is automatically hidden when the user starts performing another action in the editor. -Other -[`HintManager`](upsource:///platform/platform-api/src/com/intellij/codeInsight/hint/HintManager.java) -methods can be used for displaying other kinds of non-modal notification hints over an editor. +Other [`HintManager`](upsource:///platform/platform-api/src/com/intellij/codeInsight/hint/HintManager.java) methods can be used for displaying other kinds of non-modal notification hints over an editor. ### Top-Level Notifications -The most general way to display non-modal notifications is to use the -[`Notifications`](upsource:///platform/platform-api/src/com/intellij/notification/Notifications.java) -class. +The most general way to display non-modal notifications is to use the [`Notifications`](upsource:///platform/platform-api/src/com/intellij/notification/Notifications.java) class. It has two main advantages: +* The user can control the way each notification type is displayed under `Settings | Appearance & Behavior | Notifications` +* All displayed notifications are gathered in the Event Log tool window and can be reviewed later -* The user can control the way each notification type is displayed under `Settings | Appearance & Behavior | Notifications` - -* All displayed notifications are gathered in the Event Log tool window and can be reviewed later - -The specific method used to display a notification is -[`Notifications.Bus.notify()`](upsource:///platform/platform-api/src/com/intellij/notification/Notifications.java). +The specific method used to display a notification is [`Notifications.Bus.notify()`](upsource:///platform/platform-api/src/com/intellij/notification/Notifications.java). If the current Project is known, please use overload with `Project` parameter, so the notification is shown in its associated frame. The text of the notification can include HTML tags. -Use `Notification.addAction(AnAction)` to add links below the content, use [`NotificationAction`](upsource:///platform/platform-api/src/com/intellij/notification/NotificationAction.java) for convenience. +Use `Notification.addAction(AnAction)` to add links below the content, use [`NotificationAction`](upsource:///platform/platform-api/src/com/intellij/notification/NotificationAction.java) for convenience. -The `groupDisplayId` parameter of the -[`Notification`](upsource:///platform/platform-api/src/com/intellij/notification/Notification.java) -constructor specifies a notification type. +The `groupDisplayId` parameter of the [`Notification`](upsource:///platform/platform-api/src/com/intellij/notification/Notification.java) constructor specifies a notification type. The user can choose the display type corresponding to each notification type under `Settings | Appearance and Behavior | Notifications`. -To specify the preferred display type, you need to use -[`NotificationGroup`](upsource:///platform/platform-api/src/com/intellij/notification/NotificationGroup.kt) -to create notifications. +To specify the preferred display type, you need to use [`NotificationGroup`](upsource:///platform/platform-api/src/com/intellij/notification/NotificationGroup.kt) to create notifications. #### Example -Simple use of notifications using -[`NotificationGroup`](upsource:///platform/platform-api/src/com/intellij/notification/NotificationGroup.kt). +Simple use of notifications using [`NotificationGroup`](upsource:///platform/platform-api/src/com/intellij/notification/NotificationGroup.kt). ```java public class MyGroovyDSLErrorsNotifier { - private final NotificationGroup NOTIFICATION_GROUP = + private final NotificationGroup NOTIFICATION_GROUP = new NotificationGroup("Groovy DSL errors", NotificationDisplayType.BALLOON, true); public Notification notify(String content) { @@ -72,9 +56,7 @@ public class MyGroovyDSLErrorsNotifier { } ``` -Usage of the class with -[`NotificationGroup`](upsource:///platform/platform-api/src/com/intellij/notification/NotificationGroup.kt) -above. +Usage of the class with [`NotificationGroup`](upsource:///platform/platform-api/src/com/intellij/notification/NotificationGroup.kt) above. ```java MyGroovyDSLErrorsNotifier myGroovyDSLErrorsNotifier = new MyGroovyDSLErrorsNotifier(); diff --git a/user_interface_components/popups.md b/user_interface_components/popups.md index 6630a4be9..c0166cf53 100644 --- a/user_interface_components/popups.md +++ b/user_interface_components/popups.md @@ -10,38 +10,21 @@ Making use of these controls in your plugin ensures a consistent user experience Popups can optionally display a title, are optionally movable and resizable (and support remembering their size), and can be nested (show another popup when an item is selected). -The -[`JBPopupFactory`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/popup/JBPopupFactory.java) -interface allows you to create popups that display different kinds of components, depending on your specific needs. +The [`JBPopupFactory`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/popup/JBPopupFactory.java) interface allows you to create popups that display different kinds of components, depending on your specific needs. The most commonly used methods are: -* `createComponentPopupBuilder()` is the most generic one, allowing you to show any -[Swing](https://docs.oracle.com/javase/tutorial/uiswing/start/index.html) -component in the popup. - -* `createPopupChooserBuilder()` creates a popup for choosing one or more items from a plain `java.util.List` - -* `createConfirmation()` creates a popup for choosing between two options, and performing different actions depending on which option is selected. - -* `createActionGroupPopup()` creates a popup which shows the actions from an action group and executes the action selected by the user. +* `createComponentPopupBuilder()` is the most generic one, allowing you to show any [Swing](https://docs.oracle.com/javase/tutorial/uiswing/start/index.html) component in the popup. +* `createPopupChooserBuilder()` creates a popup for choosing one or more items from a plain `java.util.List` +* `createConfirmation()` creates a popup for choosing between two options, and performing different actions depending on which option is selected. +* `createActionGroupPopup()` creates a popup which shows the actions from an action group and executes the action selected by the user. Action group popups support different ways of choosing an action from the keyboard, in additional to the normal arrow keys. -By passing one of the constants in the -[`ActionSelectionAid`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/popup/JBPopupFactory.java) -enumeration, you can choose whether an action can be selected by pressing a key corresponding to its sequential number, typing part of its text (speed search) or pressing a mnemonic character. +By passing one of the constants in the [`ActionSelectionAid`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/popup/JBPopupFactory.java) enumeration, you can choose whether an action can be selected by pressing a key corresponding to its sequential number, typing part of its text (speed search) or pressing a mnemonic character. For popups with a fixed set of items, the recommended selection method is sequential numbering; for popups with a variable and potentially large number of items, speed search typically works best. -If you need to create a list-like popup which is more flexible than a simple -[`JList`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JList.html) -but don't want to represent the possible choices as actions in an action group, you can work directly with the -[`ListPopupStep`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/popup/ListPopupStep.java) -interface and the -[`JBPopupFactory.createListPopup()`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/popup/JBPopupFactory.java) -method. -Normally you don't need to implement the entire interface; instead, you can derive from the -[`BaseListPopupStep`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/popup/util/BaseListPopupStep.java) -class. +If you need to create a list-like popup which is more flexible than a simple [`JList`](https://docs.oracle.com/javase/8/docs/api/javax/swing/JList.html) but don't want to represent the possible choices as actions in an action group, you can work directly with the [`ListPopupStep`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/popup/ListPopupStep.java) interface and the [`JBPopupFactory.createListPopup()`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/popup/JBPopupFactory.java) method. +Normally you don't need to implement the entire interface; instead, you can derive from the [`BaseListPopupStep`](upsource:///platform/platform-api/src/com/intellij/openapi/ui/popup/util/BaseListPopupStep.java) class. The key methods to override are `getTextFor()` (returning the text to display for an item) and `onChosen()` (called when an item is selected). By returning a new popup step from the `onChosen()` method, you can implement hierarchical (nested) popups. @@ -50,7 +33,4 @@ You can let the IntelliJ Platform automatically choose the position based on the > **NOTE** The `show()` methods return immediately and do not wait for the popup to be closed. -If you need to perform some action when the popup is closed, you can either attach a listener to it using the `addListener()` method, override a method of the popup contents such as -[`PopupStep.onChosen()`](upsource:///platform/core-ui/src/openapi/ui/popup/PopupStep.java), -or attach an event handler to your own component within the popup. - +If you need to perform some action when the popup is closed, you can either attach a listener to it using the `addListener()` method, override a method of the popup contents such as [`PopupStep.onChosen()`](upsource:///platform/core-ui/src/openapi/ui/popup/PopupStep.java), or attach an event handler to your own component within the popup. diff --git a/user_interface_components/tool_windows.md b/user_interface_components/tool_windows.md index db58eb1ba..19bac8104 100644 --- a/user_interface_components/tool_windows.md +++ b/user_interface_components/tool_windows.md @@ -5,7 +5,9 @@ title: Tool Windows ## Tool Windows -_Tool windows_ are child windows of the IDE used to display information. These windows generally have their own toolbars (referred to as _tool window bars_) along the outer edges of the main window containing one or more _tool window buttons_, which activate panels displayed on the left, bottom and right sides of the main IDE window. For detailed information about tool windows, please see [IntelliJ IDEA Web Help ](https://www.jetbrains.com/idea/help/tool-windows.html). +_Tool windows_ are child windows of the IDE used to display information. +These windows generally have their own toolbars (referred to as _tool window bars_) along the outer edges of the main window containing one or more _tool window buttons_, which activate panels displayed on the left, bottom and right sides of the main IDE window. +For detailed information about tool windows, please see [IntelliJ IDEA Web Help ](https://www.jetbrains.com/idea/help/tool-windows.html). Each side contains two tool window groups, the primary and the secondary one, and only one tool window from each group can be active at a time. @@ -27,23 +29,18 @@ The extension point attributes specify all the data which is necessary to displa * The `icon` to display on the tool window button (13x13 pixels) -In addition to that, specify the *factory class* - the name of a class implementing the -[`ToolWindowFactory`](upsource:///platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java) -interface. +In addition to that, specify the *factory class* - the name of a class implementing the [`ToolWindowFactory`](upsource:///platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java) interface. When the user clicks on the tool window button, the `createToolWindowContent()` method of the factory class is called, and initializes the UI of the tool window. This procedure ensures that unused tool windows don't cause any overhead in startup time or memory usage: if a user does not interact with the tool window of a plugin, no plugin code will be loaded or executed. -If the tool window of a plugin doesn't need to be displayed for all projects: +If the tool window of a plugin doesn't need to be displayed for all projects: * For versions 2020.1 and later, also implement the `isApplicable(Project)` method. * For versions 2019.3 and earlier, also specify the `conditionClass` attribute for the `` element: the FQN of a class implementing [`Condition`](upsource:///platform/util-rt/src/com/intellij/openapi/util/Condition.java), which can be the same class as the tool window factory implementation. See [Creation of Plugin](#creation-of-plugin) for more information. -Note the condition is evaluated only once when the project is loaded; -to show and hide a tool window dynamically while the user is working with the project use the second method for tool window registration. +Note the condition is evaluated only once when the project is loaded; to show and hide a tool window dynamically while the user is working with the project use the second method for tool window registration. -The second method involves simply calling -[`ToolWindowManager.registerToolWindow()`](upsource:///platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.kt) -from the plugin code. +The second method involves simply calling [`ToolWindowManager.registerToolWindow()`](upsource:///platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.kt) from the plugin code. The method has multiple overloads that can be used depending on the task. When using an overload that takes a component, the component becomes the first content (tab) displayed in the tool window. @@ -51,22 +48,18 @@ Displaying the contents of many tool windows requires access to the indices. Because of that, tool windows are normally disabled while building indices, unless `true` is passed as the value of `canWorkInDumbMode` to the `registerToolWindow()` function. As mentioned previously, tool windows can contain multiple tabs, or contents. -To manage the contents of a tool window, call -[`ToolWindow.getContentManager()`](upsource:///platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java). -To add a tab (content), first create it by calling -[`ContentManager.getFactory().createContent()`](upsource:///platform/platform-api/src/com/intellij/ui/content/ContentManager.java), -and then to add it to the tool window using -[`ContentManager.addContent()`](upsource:///platform/platform-api/src/com/intellij/ui/content/ContentManager.java). +To manage the contents of a tool window, call [`ToolWindow.getContentManager()`](upsource:///platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java). +To add a tab (content), first create it by calling [`ContentManager.getFactory().createContent()`](upsource:///platform/platform-api/src/com/intellij/ui/content/ContentManager.java), and then to add it to the tool window using [`ContentManager.addContent()`](upsource:///platform/platform-api/src/com/intellij/ui/content/ContentManager.java). A plugin can control whether the user is allowed to close tabs either globally or on a per-tab basis. -The former is done by passing the `canCloseContents` parameter to the `registerToolWindow()` function, or by specifying -`canCloseContents="true"` in `plugin.xml`. The default value is `false`; calling `setClosable(true)` on `ContentManager` content will be ignored unless `canCloseContents` is explicitly set. -If closing tabs is enabled in general, a plugin can disable closing of specific tabs by calling -[`Content.setCloseable(false)`](upsource:///platform/platform-api/src/com/intellij/ui/content/Content.java). +The former is done by passing the `canCloseContents` parameter to the `registerToolWindow()` function, or by specifying `canCloseContents="true"` in `plugin.xml`. +The default value is `false`; calling `setClosable(true)` on `ContentManager` content will be ignored unless `canCloseContents` is explicitly set. +If closing tabs is enabled in general, a plugin can disable closing of specific tabs by calling [`Content.setCloseable(false)`](upsource:///platform/platform-api/src/com/intellij/ui/content/Content.java). ## How to Create a Tool Window? -The IntelliJ Platform provides the `com.intellij.toolWindow` [extension point](/basics/plugin_structure/plugin_extensions.md) to create and configure custom tool windows. This extension point is declared using the [`ToolWindowEP`](upsource:///platform/platform-api/src/com/intellij/openapi/wm/ToolWindowEP.java) bean class. +The IntelliJ Platform provides the `com.intellij.toolWindow` [extension point](/basics/plugin_structure/plugin_extensions.md) to create and configure custom tool windows. +This extension point is declared using the [`ToolWindowEP`](upsource:///platform/platform-api/src/com/intellij/openapi/wm/ToolWindowEP.java) bean class. ### Creation of Plugin @@ -87,16 +80,17 @@ To clarify the above procedure, consider the following fragment of the `plugin.x ```xml - ``` ### Sample Plugin -To clarify how to develop plugins that create tool windows, consider the **toolWindow** sample plugin available in the [code_samples](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/tool_window) directory of the SDK documentation. This plugin creates the **Sample Calendar** tool window that displays the system date, time and time zone. +To clarify how to develop plugins that create tool windows, consider the **toolWindow** sample plugin available in the [code_samples](https://github.com/JetBrains/intellij-sdk-code-samples/tree/master/tool_window) directory of the SDK documentation. +This plugin creates the **Sample Calendar** tool window that displays the system date, time and time zone. **To run the toolWindow plugin** @@ -106,6 +100,7 @@ To view or modify the project settings, open the [Project Structure](https://www 3. Run the plugin by choosing the **Run | Run** on the main menu. If necessary, change the [Run/Debug Configurations](https://www.jetbrains.com/help/idea/run-debug-configuration-plugin.html). -The plugin creates the **Sample Calendar** tool window. When opened, this tool window is similar to the following screen: +The plugin creates the **Sample Calendar** tool window. +When opened, this tool window is similar to the following screen: ![Sample Calendar](img/sample_calendar.png) diff --git a/user_interface_components/user_interface_components.md b/user_interface_components/user_interface_components.md index 2b04d8a75..a39207d76 100644 --- a/user_interface_components/user_interface_components.md +++ b/user_interface_components/user_interface_components.md @@ -3,12 +3,13 @@ title: User Interface Components --- -The IntelliJ Platform includes a large number of custom Swing components. Using those components in your plugins will ensure that your plugin looks and works consistently with the UI of the rest of the IDE, and can often reduce the code size compared to using the default Swing components. +The IntelliJ Platform includes a large number of custom Swing components. +Using those components in your plugins will ensure that your plugin looks and works consistently with the UI of the rest of the IDE, and can often reduce the code size compared to using the default Swing components. > **TIP** Use [UI Inspector](/reference_guide/internal_actions/internal_ui_inspector.md) to locate the underlying Swing component implementation or to inspect an existing UI at runtime. -> **NOTE** The recommended way of building UIs on the IntelliJ Platform (2019.2 and later) is using -[Kotlin UI DSL](/user_interface_components/kotlin_ui_dsl.md). Using GUI designer with Kotlin is currently [not supported](https://youtrack.jetbrains.com/issue/KT-6660). +> **NOTE** The recommended way of building UIs on the IntelliJ Platform (2019.2 and later) is using [Kotlin UI DSL](/user_interface_components/kotlin_ui_dsl.md). +> Using GUI designer with Kotlin is currently [not supported](https://youtrack.jetbrains.com/issue/KT-6660). The following components are particularly noteworthy: @@ -26,4 +27,3 @@ The following components are particularly noteworthy: * Messages * JBSplitter * JBTabs -