New Topic: Postfix Completion (#788)

This commit is contained in:
Karol Lewandowski 2022-06-03 08:54:01 +02:00 committed by GitHub
parent 424d882210
commit 5807d68941
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 229 additions and 4 deletions

View File

@ -186,6 +186,10 @@
<toc-element toc-title="Navigation"/>
<toc-element id="editing.md">
<toc-element toc-title="Code Completion"/>
<toc-element id="postfix_completion.md">
<toc-element id="postfix_templates.md"/>
<toc-element id="advanced_postfix_templates.md"/>
</toc-element>
<toc-element id="templates.md">
<toc-element id="live_templates.md">
<toc-element id="template_support.md"/>

View File

@ -3,6 +3,7 @@
<!-- Copyright 2000-2022 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. -->
* Code Completion
* [](postfix_completion.md)
* [](templates.md)
* [](live_templates.md)
* [](file_and_code_templates.md)

View File

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

View File

@ -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"}

View File

@ -0,0 +1,43 @@
[//]: # (title: Postfix Completion)
<!-- Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<excerpt>Postfix completion allows generating or wrapping existing code into additional constructs without navigating the caret back.</excerpt>
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()<caret>
}
```
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<ENTER>
}
```
When the template is applied, the above code is expanded to:
```java
void confirmOrder(Cart cart) {
Money deliveryCost = cart.getDeliveryType().getDeliveryCost();<caret>
}
```
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)

View File

@ -0,0 +1,95 @@
[//]: # (title: Advanced Postfix Templates)
<!-- Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<excerpt>Advanced postfix templates provide additional features like editing possibilities, expression selector, etc.</excerpt>
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 <menupath>Code | Surround With...</menupath> 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`.

View File

@ -0,0 +1,79 @@
[//]: # (title: Postfix Templates)
<!-- Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<excerpt>Postfix templates implement possibility to modify or wrap the existing code in additional constructs without navigating the caret back.</excerpt>
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 <path>resources</path> in the <path>postfixTemplates/_$TEMPLATE_NAME$_</path> 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 <path>IntroduceVariablePostfixTemplate</path>.
Providing the description explaining the template purpose and context details is achieved by creating the <path>description.html</path> file.
Providing the code snippets showing the template in "before" and "after" expanding states is achieved via the <path>before._$EXTENSION$_.template</path> and <path>after._$EXTENSION$_.template</path> files accordingly.
The _$EXTENSION$_ placeholder should be replaced with the extension of the template language, e.g., <path>before.kt.template</path> for a Kotlin template.
The code snippets included in the example files can use the `<spot>` 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 <menupath>Settings/Preferences | Editor | General | Postfix Completion</menupath> settings page, making it easier for users to understand how a template is expanded, e.g.:
- <path>before.java.template</path>:
```java
<spot>cart.getProducts()</spot>.var
```
- <path>after.java.template</path>:
```java
List<Product> products = cart.getProducts();<spot></spot>
```
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:
<compare title-before="Content" title-after="Rendition">
<code style="block" lang="Text">
cart.getProducts()$key
</code>
<code style="block" lang="Text">
cart.getProducts().var
</code>
</compare>
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.