diff --git a/ijs.tree b/ijs.tree index d1d0d9716..e8cdb49dc 100644 --- a/ijs.tree +++ b/ijs.tree @@ -186,6 +186,10 @@ + + + + diff --git a/topics/basics/editing.md b/topics/basics/editing.md index 2154d7452..fe7f15ab7 100644 --- a/topics/basics/editing.md +++ b/topics/basics/editing.md @@ -3,8 +3,9 @@ * Code Completion +* [](postfix_completion.md) * [](templates.md) - * [](live_templates.md) - * [](file_and_code_templates.md) + * [](live_templates.md) + * [](file_and_code_templates.md) * [](code_documentation.md) * [](code_intentions.md) diff --git a/topics/intro/content_updates.md b/topics/intro/content_updates.md index e33fc6631..9c2419c4a 100644 --- a/topics/intro/content_updates.md +++ b/topics/intro/content_updates.md @@ -12,7 +12,10 @@ See [GitHub Changelog](https://github.com/JetBrains/intellij-sdk-docs/commits/ma ## 2022 -### Jun-02 +### June-22 + +Postfix Completion +: Add [](postfix_completion.md) section explaining how to implement generating or wrapping the existing code into additional constructs without navigating the caret back. Gradle IntelliJ Plugin : Add [](tools_gradle_intellij_plugin.md) documentation to the Appendix III – Tools diff --git a/topics/reference_guide/custom_language_support/surround_with.md b/topics/reference_guide/custom_language_support/surround_with.md index 5edba5a5b..310f73442 100644 --- a/topics/reference_guide/custom_language_support/surround_with.md +++ b/topics/reference_guide/custom_language_support/surround_with.md @@ -13,6 +13,6 @@ Once the user selects a specific surrounder from the popup menu, the [`Surrounde **Example:** [`SurroundDescriptor`](upsource:///plugins/groovy/src/org/jetbrains/plugins/groovy/lang/surroundWith/GroovySurroundDescriptor.java) for Groovy plugin -> See the [](live_templates.md) section for information on how to support simple code surrounding with the *Live Templates* feature. +> See the [](live_templates.md) and [](advanced_postfix_templates.md#surround-postfix-templates) sections for information on how to support code surrounding with other IDE features. > {type="note"} diff --git a/topics/tutorials/postfix_completion.md b/topics/tutorials/postfix_completion.md new file mode 100644 index 000000000..a82b2cc41 --- /dev/null +++ b/topics/tutorials/postfix_completion.md @@ -0,0 +1,43 @@ +[//]: # (title: Postfix Completion) + + + +Postfix completion allows generating or wrapping existing code into additional constructs without navigating the caret back. + +The +[Postfix Completion](https://www.jetbrains.com/help/idea/auto-completing-code.html#postfix_completion) +functionality allows developers to wrap a code fragment with a predefined template by typing a template abbreviation just after an expression meant to be wrapped, expanded, or modified. +It relieves developers from typing repetitive or non-trivial code or helps to create the code faster, e.g., often it is convenient to write a code part and surround it with the required block without navigating the caret backward. + +Consider a situation where a developer is not very familiar with a current Java project API and doesn't know how to name a variable that will be a result of an expression they want to type. +The postfix completion makes it possible to write an expression at first and create a variable assignment with suggested names by adding a postfix template abbreviation at the end of the expression. + +Assume that a user typed the following Java code: + +```java +void confirmOrder(Cart cart) { + cart.getDeliveryType().getDeliveryCost() +} +``` + +To avoid moving the caret to the beginning of the line, the user can quickly create a variable assignment by adding the `.var` postfix abbreviation and expanding the template: + +```java +void confirmOrder(Cart cart) { + cart.getDeliveryType().getDeliveryCost().var +} +``` + +When the template is applied, the above code is expanded to: + +```java +void confirmOrder(Cart cart) { + Money deliveryCost = cart.getDeliveryType().getDeliveryCost(); +} +``` + +In addition, the user can choose the best matching variable name from the name suggestions popup. + +These sections describe how to implement Postfix Templates, and their associated building blocks, to plugins: +- [](postfix_templates.md) +- [](advanced_postfix_templates.md) diff --git a/topics/tutorials/postfix_completion/advanced_postfix_templates.md b/topics/tutorials/postfix_completion/advanced_postfix_templates.md new file mode 100644 index 000000000..bda13b2c7 --- /dev/null +++ b/topics/tutorials/postfix_completion/advanced_postfix_templates.md @@ -0,0 +1,95 @@ +[//]: # (title: Advanced Postfix Templates) + + + +Advanced postfix templates provide additional features like editing possibilities, expression selector, etc. + +While [simple templates](postfix_templates.md) can be handled by extending +[`PostfixTemplate`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java) +class directly, more advanced templates require additional functionalities like selecting the expression that a template should be applied to or editing a template content. +The IntelliJ Platform provides the base classes simplifying advanced template's features implementation. + +## Postfix Templates With Expression Selector + +In some contexts, it is not obvious what expression a template should be applied to. +Consider the following Java code with the `var` postfix template at the end: + +```java +order.calculateWeight() > getMaxWeight(order.getDeliveryType()).var +``` + +In the above code, a postfix template could be applied to the `getMaxWeight()` method invocation and the entire comparison expression depending on the user's intention. +The postfix template implementation could automatically apply the template on the topmost or the closest applicable expression, but it is reasonable to leave the expression selection for the user. + +Postfix templates with expression selector can be achieved by implementing +[`PostfixTemplateWithExpressionSelector`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java) +and +[`PostfixTemplateExpressionSelector`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java) +classes. + +**Example:** +[`IntroduceFieldPostfixTemplate`](upsource:///java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java) +introduces a Java class field, allowing to select one of the non-void expressions at the current offset. + +## Live Template Syntax-Based Postfix Templates + +The IntelliJ Platform-based IDEs provide the [Live Templates](https://www.jetbrains.com/help/idea/using-live-templates.html) feature. +It allows defining a template text with dynamic expressions, replaced with actual values depending on the context. +If the implemented postfix template's expanding behavior can be achieved with the live template syntax, it is much easier to extend the +[`StringBasedPostfixTemplate`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java) +than implementing the expansion behavior programmatically. + +**Example:** [`StreamPostfixTemplate`](upsource:///java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StreamPostfixTemplate.java) wraps array expression within the `Arrays.stream()` method. + +> See the [](live_templates.md) section in SDK Docs for information on implementing the live templates feature in a plugin. +> +{type="note"} + +## Editable Postfix Templates + +All postfix templates that return `true` from the +[`PostfixTemplate.isEditable()`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java) +method and have a key starting with `.` (dot) can be edited. +In the simplest case, only the template's name can be edited. +To provide more advanced editing possibilities, like creating new templates in the settings dialog, editing the template's content, variables, expression conditions, etc., a plugin must implement the related +[`PostfixTemplateProvider's`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java) +methods: + +- `PostfixTemplateProvider.createEditor()` - returns an instance of the + [`PostfixTemplateEditor`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateEditor.java) + class which is responsible for building the UI settings for a particular template and creating a template from the settings provided in this UI. + The editor UI may contain settings controls other than the textual editor, like lists, checkboxes, etc. +- `PostfixTemplateProvider.writeExternalTemplate()` / `readExternalTemplate()` - serializes/deserializes a given template to/from XML elements. + Serialized template data is stored in the + [`PostfixTemplateStorage`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplateStorage.java) + [persistent component](persisting_state_of_components.md). + +Implementing template, editor, and serialization methods from scratch is a tedious task, so the IntelliJ Platform provides classes that help implement editable templates: +- [`EditablePostfixTemplateWithMultipleExpressions`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplateWithMultipleExpressions.java) + for editable templates with expression selector and conditions limiting the applicable contexts. + Like [](#live-template-syntax-based-postfix-templates), it is text-based and uses the same live template syntax. +- [`PostfixTemplateEditorBase`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplateEditorBase.java) + for editors implementing the most common features like editing content, expression conditions, or using the topmost expression for template expanding +- Utility class + [`PostfixTemplatesUtils`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java) + providing methods related to editable template data serialization + +**Examples:** +- [`JavaPostfixTemplateProvider`](upsource:///java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java) + providing Java editable templates +- [`JavaPostfixTemplateEditor`](upsource:///java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/JavaPostfixTemplateEditor.java) + implementing editor for Java editable templates +- [`ObjectsRequireNonNullPostfixTemplate`](upsource:///java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ObjectsRequireNonNullPostfixTemplate.java) + implementing template wrapping the selected expression in `Objects.requireNonNull()` method + +## Surround Postfix Templates + +Existing +[`Surrounder`](upsource:///platform/lang-api/src/com/intellij/lang/surroundWith/Surrounder.java) +implementations of the [](surround_with.md) feature required to invoke the Code | Surround With... action can be reused for postfix completion by extending the +[`SurroundPostfixTemplateBase`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java) +class and returning the surrounder object from the `getSurrounder()` method. + +**Example:** +[`NotNullCheckPostfixTemplate`](upsource:///java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java) +surrounding the selected expression with an `if` statement checking if the expression is `null`. diff --git a/topics/tutorials/postfix_completion/postfix_templates.md b/topics/tutorials/postfix_completion/postfix_templates.md new file mode 100644 index 000000000..d544276f0 --- /dev/null +++ b/topics/tutorials/postfix_completion/postfix_templates.md @@ -0,0 +1,79 @@ +[//]: # (title: Postfix Templates) + + + +Postfix templates implement possibility to modify or wrap the existing code in additional constructs without navigating the caret back. + +The IntelliJ Platform allows plugins to provide custom postfix templates specific to the supported languages, frameworks, or libraries. + +To provide custom postfix templates for an existing or custom language, register an implementation of +[`PostfixTemplateProvider`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java) +in the `com.intellij.codeInsight.template.postfixTemplateProvider` extension point (EP). + +The `PostfixTemplateProvider` extension contains the list of templates that extend the +[`PostfixTemplate`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java) +class. +During the code completion mechanism, all postfix template providers registered for the current language are queried for their templates. +All templates enabled and applicable in the current context will be added to the completion popup items set. + +**Examples:** +- [`JavaPostfixTemplateProvider`](upsource:///java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java) providing Java postfix templates +- [`PyPostfixTemplateProvider`](upsource:///python/src/com/jetbrains/python/codeInsight/postfix/PyPostfixTemplateProvider.java) providing Python postfix templates + +## Postfix Templates Implementation + +The simplest way to create a postfix template is by extending the +[`PostfixTemplate`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java) +class and implementing the key methods: +- `boolean isApplicable()` determining whether the template can be used in the context described by parameters +- `void expand()` inserting the template content in the editor + +**Examples:** +- [`InstanceofExpressionPostfixTemplate`](upsource:///java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java) surrounding an expression with the _instanceof_ check +- [`TryWithResourcesPostfixTemplate`](upsource:///java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java) wrapping a selected expression in _try-with-resources_ block + +> See the [](advanced_postfix_templates.md) section for information on how to implement postfix templates with more advanced features and editing possibilities. +> +{type="note"} + +## Postfix Template Description + +All postfix templates must provide descriptions and examples showing the code before and after a template is expanded. +The files describing the template must be placed in the plugin's resources in the postfixTemplates/_$TEMPLATE_NAME$_ where the _$TEMPLATE_NAME$_ directory must match the simple name of the template class, +e.g., for a template implemented in `com.example.IntroduceVariablePostfixTemplate` class, the directory name should be named as IntroduceVariablePostfixTemplate. + +Providing the description explaining the template purpose and context details is achieved by creating the description.html file. + +Providing the code snippets showing the template in "before" and "after" expanding states is achieved via the before._$EXTENSION$_.template and after._$EXTENSION$_.template files accordingly. +The _$EXTENSION$_ placeholder should be replaced with the extension of the template language, e.g., before.kt.template for a Kotlin template. + +The code snippets included in the example files can use the `` marker, which should surround the most important code parts, e.g., expression to expand and position of the caret after expanding. +Marked parts will be highlighted in the Settings/Preferences | Editor | General | Postfix Completion settings page, making it easier for users to understand how a template is expanded, e.g.: +- before.java.template: + ```java + cart.getProducts().var + ``` + +- after.java.template: + ```java + List products = cart.getProducts(); + ``` + +Template example files can also use the `$key` placeholder which is replaced with the actual template key in the preview UI, e.g., consider a template with the `var` key: + + + + cart.getProducts()$key + + + cart.getProducts().var + + + +The gutter icons for a postfix template class allow navigating to the corresponding description and before/after files in plugin resources. + +**Example:** +[`TryWithResourcesPostfixTemplate`](upsource:///java/java-impl/src/postfixTemplates/TryWithResourcesPostfixTemplate) +directory containing description files for +[`TryWithResourcesPostfixTemplate`](upsource:///java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryWithResourcesPostfixTemplate.java) +template.