Changes driven by plugin revisions
@ -2,63 +2,31 @@
|
||||
title: 7. Annotator
|
||||
---
|
||||
|
||||
Annotator helps highlight and annotate any code based on specific rules.
|
||||
An [Annotator](/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md#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.
|
||||
|
||||
### 7.1. Define an annotator
|
||||
|
||||
In this tutorial we will annotate usages of our properties within Java code.
|
||||
Let's consider a literal which starts with *"simple:"* as a usage of our property.
|
||||
* bullet item
|
||||
{:toc}
|
||||
|
||||
## 7.1. Define an Annotator
|
||||
The `SimpleAnnotator` subclasses [`Annotator`](upsource:///platform/analysis-api/src/com/intellij/lang/annotation/Annotator.java).
|
||||
Consider a literal string that starts with "simple:" as a prefix of a Simple language key.
|
||||
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:
|
||||
```java
|
||||
package com.simpleplugin;
|
||||
|
||||
import com.intellij.lang.annotation.*;
|
||||
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.simpleplugin.psi.SimpleProperty;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SimpleAnnotator implements Annotator {
|
||||
@Override
|
||||
public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
if (element instanceof PsiLiteralExpression) {
|
||||
PsiLiteralExpression literalExpression = (PsiLiteralExpression) element;
|
||||
String value = literalExpression.getValue() instanceof String ? (String) literalExpression.getValue() : null;
|
||||
|
||||
if (value != null && value.startsWith("simple" + ":")) {
|
||||
Project project = element.getProject();
|
||||
String key = value.substring(7);
|
||||
List<SimpleProperty> properties = SimpleUtil.findProperties(project, key);
|
||||
if (properties.size() == 1) {
|
||||
TextRange range = new TextRange(element.getTextRange().getStartOffset() + 8,
|
||||
element.getTextRange().getEndOffset() - 1);
|
||||
Annotation annotation = holder.createInfoAnnotation(range, null);
|
||||
annotation.setTextAttributes(DefaultLanguageHighlighterColors.LINE_COMMENT);
|
||||
} else if (properties.size() == 0) {
|
||||
TextRange range = new TextRange(element.getTextRange().getStartOffset() + 8,
|
||||
element.getTextRange().getEndOffset() - 1);
|
||||
holder.createErrorAnnotation(range, "Unresolved property");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleAnnotator.java %}
|
||||
```
|
||||
|
||||
### 7.2. Register the annotator
|
||||
|
||||
## 7.2. Register the Annotator
|
||||
Using an extension point, register the Simple language annotator class with the IntelliJ Platform:
|
||||
```xml
|
||||
<annotator language="JAVA" implementationClass="com.simpleplugin.SimpleAnnotator"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<annotator language="JAVA" implementationClass="com.intellij.sdk.language.SimpleAnnotator"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 7.3. Run the project
|
||||
|
||||
Let's define the following Java file and check if the IDE resolves a property.
|
||||
|
||||
## 7.3. Run the Project
|
||||
As a test, define the following Java file containing a Simple language `prefix:value` pair:
|
||||
```java
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
@ -67,9 +35,12 @@ 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:
|
||||
|
||||
If we type an undefined property name, it will annotate the code with a error.
|
||||
{:width="800px"}
|
||||
|
||||

|
||||
If the property is an undefined name, the annotator will annotate the code with an error.
|
||||
|
||||
{: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.
|
@ -2,38 +2,49 @@
|
||||
title: 16. Code Style Setting
|
||||
---
|
||||
|
||||
Code style settings allow defining formatting options. A code style settings provider will create an instance of the settings, and also create an options page in order to edit them. In this example, we'll create a page that uses the default language code style settings, customised by a language code style settings provider.
|
||||
[Code style settings](/reference_guide/custom_language_support/code_formatting.md#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, customised by a language code style settings provider.
|
||||
|
||||
### 16.1. Define code style settings
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
## 16.1. Define Code Style Settings
|
||||
Define a code style settings for Simple language by subclassing [`CustomCodeStyleSettings`](upsource:///platform/lang-api/src/com/intellij/psi/codeStyle/CustomCodeStyleSettings.java).
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleCodeStyleSettings.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleCodeStyleSettings.java %}
|
||||
```
|
||||
|
||||
### 16.2. Define code style settings provider
|
||||
|
||||
## 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.
|
||||
Define a code style settings provider for Simple language by subclassing [`CodeStyleSettingsProvider`](upsource:///platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsProvider.java).
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleCodeStyleSettingsProvider.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleCodeStyleSettingsProvider.java %}
|
||||
```
|
||||
|
||||
### 16.3. Register the code style settings provider
|
||||
|
||||
## 16.3. Register the Code Style Settings Provider
|
||||
The `SimpleCodeStyleSettingsProvider` implementation is registered with the IntelliJ Platform in `plugin.xml` using the `codeStyleSettingsProvider` extension point.
|
||||
```xml
|
||||
<codeStyleSettingsProvider implementation="com.simpleplugin.SimpleCodeStyleSettingsProvider"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<codeStyleSettingsProvider implementation="com.intellij.sdk.language.SimpleCodeStyleSettingsProvider"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 16.4. Define language code style settings provider
|
||||
|
||||
## 16.4. Define the Language Code Style Settings Provider
|
||||
Define a code style settings provider for Simple language by subclassing [`LanguageCodeStyleSettingsProvider`](upsource:///platform/lang-api/src/com/intellij/psi/codeStyle/LanguageCodeStyleSettingsProvider.java), which provides common code style settings for a specific language.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleLanguageCodeStyleSettingsProvider.java %}
|
||||
```
|
||||
|
||||
### 16.5. Register the language code style settings provider
|
||||
|
||||
## 16.5. Register the Language Code Style Settings Provider
|
||||
The `SimpleLanguageCodeStyleSettingsProvider` implementation is registered with the IntelliJ Platform in `plugin.xml` using the `langCodeStyleSettingsProvider` extension point.
|
||||
```xml
|
||||
<langCodeStyleSettingsProvider implementation="com.simpleplugin.SimpleLanguageCodeStyleSettingsProvider"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<langCodeStyleSettingsProvider implementation="com.intellij.sdk.language.SimpleLanguageCodeStyleSettingsProvider"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 16.6. Run the project
|
||||
## 16.6. Run the project
|
||||
In the IDE Development Instance, open the Simple language code formatting page: **Preferences/Settings \| Editor \| Code Style \| Simple**.
|
||||
|
||||

|
||||
|
@ -2,20 +2,32 @@
|
||||
title: 17. Commenter
|
||||
---
|
||||
|
||||
A commenter allows user to comment the code at the cursor or selected code automatically via corresponding actions.
|
||||
A commenter enables the user to comment out 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 "Comment with Line Comment" and "Comment with Block Comment" actions.
|
||||
|
||||
### 17.1. Define a commenter
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
## 17.1. Define a Commenter
|
||||
The Simple language commenter subclasses `Commenter`.
|
||||
This commenter defines the line comment prefix as "#".
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleCommenter.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleCommenter.java %}
|
||||
```
|
||||
|
||||
### 17.2. Register the commenter
|
||||
|
||||
## 17.2. Register the Commenter
|
||||
The `SimpleCommenter` implementation is registered with the IntelliJ Platform in `plugin.xml` using the `lang.commenter` extension point.
|
||||
```xml
|
||||
<lang.commenter language="Simple" implementationClass="com.simpleplugin.SimpleCommenter"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<lang.commenter language="Simple" implementationClass="com.intellij.sdk.language.SimpleCommenter"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 17.3. Run the project
|
||||
## 17.3. Run the Project
|
||||
Open the example Simple Language [properties file ](/tutorials/custom_language_support/lexer_and_parser_definition.md#47-run-the-project) in the IDE Development Instance.
|
||||
Place the cursor at the `website` line.
|
||||
Select **Code \| Comment with Line Comment**.
|
||||
The line is converted to a comment.
|
||||
Select **Code \| Comment with Line Comment** again, and the comment is converted back to active code.
|
||||
|
||||

|
||||
 {:width="800px"}
|
||||
|
@ -2,23 +2,31 @@
|
||||
title: 9. Completion Contributor
|
||||
---
|
||||
|
||||
Custom languages provide code completion using one of [two approaches](/reference_guide/custom_language_support/code_completion.md).
|
||||
The Simple language plugin implements the less complex of the two methods, reference completion.
|
||||
|
||||
The easiest way to provide completion is to use a completion contributor.
|
||||
|
||||
### 9.1. Define a completion contributor
|
||||
|
||||
Let's provide custom completion for values in property files.
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
## 9.1. Define a Completion Contributor
|
||||
For the purposes of this tutorial, the `simple_language` plugin provides custom completion for values in Simple language property files.
|
||||
Create a completion contributor by subclassing [`CompletionContributor`](upsource:///platform/analysis-api/src/com/intellij/codeInsight/completion/CompletionContributor.java).
|
||||
This rudimentary completion contributor always adds "Hello" to the results set, regardless of context:
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleCompletionContributor.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleCompletionContributor.java %}
|
||||
```
|
||||
|
||||
### 9.2. Register the completion contributor
|
||||
|
||||
## 9.2. Register the Completion Contributor
|
||||
The `SimpleCompletionContributor` implementation is registered with the IntelliJ Platform using the `completion.contributor` extension point.
|
||||
```xml
|
||||
<completion.contributor language="Simple" implementationClass="com.simpleplugin.SimpleCompletionContributor"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<completion.contributor language="Simple" implementationClass="com.intellij.sdk.language.SimpleCompletionContributor"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 9.3. Run the project
|
||||
## 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).
|
||||
The choice "Hello" is shown:
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
@ -2,23 +2,30 @@
|
||||
title: 11. Find Usages Provider
|
||||
---
|
||||
|
||||
A find usage provider uses a word scanner to build an index of words present in every file.
|
||||
A scanner breaks the text into words, defines the context for each word and passes it to the find usage provider.
|
||||
A [find usage provider](/reference_guide/custom_language_support/find_usages.md) uses a word scanner to build an index of words in every file.
|
||||
A scanner breaks the text into words, defines the context for each word, and passes it to the find usage provider.
|
||||
|
||||
### 11.1. Define a find usages provider
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
## 11.1. Define a Find Usages Provider
|
||||
The `SimpleFindUsagesProvider` is 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.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleFindUsagesProvider.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleFindUsagesProvider.java %}
|
||||
```
|
||||
|
||||
### 11.2. Register the find usages provider
|
||||
|
||||
## 11.2. Register the Find Usages Provider
|
||||
The `SimpleFindUsagesProvider` implementation is registered with the IntelliJ Platform using the `lang.findUsagesProvider` extension point.
|
||||
```xml
|
||||
<lang.findUsagesProvider language="Simple" implementationClass="com.simpleplugin.SimpleFindUsagesProvider"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<lang.findUsagesProvider language="Simple" implementationClass="com.intellij.sdk.language.SimpleFindUsagesProvider"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 11.3. Run the project
|
||||
## 11.3. Run the Project
|
||||
Rebuild the project, and run `simple_language` in a Development Instance.
|
||||
The IDE now supports [Find Usages](https://www.jetbrains.com/help/idea/find-highlight-usages.html) for any property with a reference:
|
||||
|
||||
Now we can call *Find Usages* for any property with a reference.
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
@ -2,24 +2,40 @@
|
||||
title: 12. Folding Builder
|
||||
---
|
||||
|
||||
A folding builder helps you to fold the code regions and replace it with specific text.
|
||||
A folding builder identifies the folding regions in the code.
|
||||
In this step of the tutorial the folding builder is used to identify folding regions and replace the regions with specific text.
|
||||
Rather than the usual practice of using a folding builder to collapse a class, method, or comments to fewer lines, the folding builder will replace Simple language keys with their corresponding values.
|
||||
|
||||
### 12.1. Define a folding builder
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
Let's replace usages of properties with its values by default.
|
||||
## 12.1. Define a Folding Builder
|
||||
The `SimpleFoldingBuilder` will replace usages of properties with their values by default.
|
||||
Start by subclassing [`FoldingBuilderEx`](upsource:///community/platform/core-api/src/com/intellij/lang/folding/FoldingBuilderEx.java)
|
||||
Note that `SimpleFoldingBuilder` also implements `DumbAware`, which means the class is allowed to run in dumb mode, when indices are in background update.
|
||||
|
||||
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 considered 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).
|
||||
|
||||
The `getPlaceholderText()` method retrieves the Simple language value corresponding to the key associated with the (ASTNode) provided.
|
||||
The IntelliJ Platform uses the value to substitute for the key when the code is folded.
|
||||
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleFoldingBuilder.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleFoldingBuilder.java %}
|
||||
```
|
||||
|
||||
### 12.2. Register the folding builder
|
||||
|
||||
## 12.2. Register the Folding Builder
|
||||
The `SimpleFoldingBuilder` implementation is registered with the IntelliJ Platform using the `lang.foldingBuilder` extension point.
|
||||
```xml
|
||||
<lang.foldingBuilder language="JAVA" implementationClass="com.simpleplugin.SimpleFoldingBuilder"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<lang.foldingBuilder language="JAVA" implementationClass="com.intellij.sdk.language.SimpleFoldingBuilder"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 12.3. Run the project
|
||||
## 12.3. Run the Project
|
||||
Rebuild the project, and run `simple_language` in a Development Instance.
|
||||
Now when a Java file is opened in the Editor it shows the property's value instead of the key.
|
||||
This is because `SimpleFoldingBuilder.isCollapsedByDefault()` always returns `true`.
|
||||
Try using **Code \| Folding \| Expand All** to show the key rather than the value.
|
||||
|
||||
Now when we open a Java file, it shows the property's value instead of the key.
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
@ -2,33 +2,38 @@
|
||||
title: 15. Formatter
|
||||
---
|
||||
|
||||
*A formatter allows to reformat the code automatically based on code style settings.*
|
||||
The IntelliJ Platform includes a powerful framework for implementing formatting for custom languages.
|
||||
A [formatter](/reference_guide/custom_language_support/code_formatting.md) enables reformatting code automatically based on code style settings.
|
||||
The formatter controls spaces, indents, wrap, and alignment.
|
||||
|
||||
### 15.1. Define a block
|
||||
|
||||
The formatter uses the blocks to receive formatting rules for each PSI element.
|
||||
Our goal is to cover each PSI element with such block. Since each block builds own children blocks we can generate extra blocks or skip any PSI elements.
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
## 15.1. Define a Block
|
||||
The formatting model builds 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 setting
|
||||
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.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleBlock.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleBlock.java %}
|
||||
```
|
||||
|
||||
### 15.2. Define a formatting model builder
|
||||
|
||||
Let's define a formatter which removes extra spaces except the single ones around the property separator.
|
||||
|
||||
## 15.2. Define a Formatting Model Builder
|
||||
Define a formatter which removes extra spaces except the single spaces around the property separator.
|
||||
For example, reformat `foo = bar` to `foo = bar`.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleFormattingModelBuilder.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleFormattingModelBuilder.java %}
|
||||
```
|
||||
|
||||
### 15.3. Register the formatter
|
||||
|
||||
## 15.3. Register the Formatter
|
||||
The `SimpleFormattingModelBuilder` implementation is registered with the IntelliJ Platform in `plugin.xml` using the `lang.formatter` extension point.
|
||||
```xml
|
||||
<lang.formatter language="Simple" implementationClass="com.simpleplugin.SimpleFormattingModelBuilder"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<lang.formatter language="Simple" implementationClass="com.intellij.sdk.language.SimpleFormattingModelBuilder"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 15.4. Run the project
|
||||
## 15.4. Run the Project
|
||||
Add some extra spaces around the `=` separator between `language` and `English`.
|
||||
Reformat the code by selecting **Code \| Show Reformat File Dialog** and choose **Run**.
|
||||
|
||||
Now add some extra spaces and reformat the code via **Code \| Reformat Code**.
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
@ -2,14 +2,15 @@
|
||||
title: 13. Go To Symbol Contributor
|
||||
---
|
||||
|
||||
*A go to symbol contributor helps user to navigate to any PSI element by its name.*
|
||||
A go to symbol contributor helps the user to navigate to any PSI element by its name.
|
||||
|
||||
### 13.1. Define helper method for generated PSI elements
|
||||
|
||||
To specify how a PSI element looks like in the *Go To Symbol* popup window, *Structure* tool window or another components, it should implement *getPresentation* method.
|
||||
|
||||
This means we need to define this method in our utility *com.simpleplugin.psi.impl.SimplePsiImplUtil* and regenerate the parser and PSI classes.
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
## 13.1. Define a Helper Method for Generated PSI Elements
|
||||
To specify how a PSI element looks like in the *Go To Symbol* popup window, *Structure* tool window or another components, it should implement `getPresentation()`.
|
||||
This means defining this method in the utility `com.intellij.sdk.language.psi.impl.SimplePsiImplUtil` and regenerate the parser and PSI classes.
|
||||
Add the following method to `SimplePsiImplUtil`:
|
||||
```java
|
||||
public static ItemPresentation getPresentation(final SimpleProperty element) {
|
||||
return new ItemPresentation() {
|
||||
@ -34,29 +35,31 @@ public static ItemPresentation getPresentation(final SimpleProperty element) {
|
||||
}
|
||||
```
|
||||
|
||||
### 13.2. Update grammar and regenerate the parser
|
||||
|
||||
## 13.2. Update Grammar and Regenerate the Parser
|
||||
Now add the `SimplePsiImplUtil.getPresentation()` to the `property` 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!
|
||||
Right click on the `Simple.bnf` file and select **Generate Parser Code**.
|
||||
```java
|
||||
property ::= (KEY? SEPARATOR VALUE?) | KEY {mixin="com.simpleplugin.psi.impl.SimpleNamedElementImpl"
|
||||
implements="com.simpleplugin.psi.SimpleNamedElement" methods=[getKey getValue getName setName getNameIdentifier getPresentation]}
|
||||
property ::= (KEY? SEPARATOR VALUE?) | KEY {mixin="com.intellij.sdk.language.psi.impl.SimpleNamedElementImpl"
|
||||
implements="com.intellij.sdk.language.psi.SimpleNamedElement" methods=[getKey getValue getName setName getNameIdentifier getPresentation]}
|
||||
```
|
||||
|
||||
Regenerate the parser by right clicking on the `Simple.bnf` file and selecting _Generate Parser Code_.
|
||||
|
||||
### 13.3. Define a go to symbol contributor
|
||||
|
||||
## 13.3. Define a Go to Symbol Contributor
|
||||
To enable the `simple_language` plugin to contribute items to "Navigate Class|File|Symbol" lists, subclass [`ChooseByNameContributor`](upsource:///platform/lang-api/src/com/intellij/navigation/ChooseByNameContributor.java) to create `SimpleChooseNameContributor`:
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleChooseByNameContributor.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleChooseByNameContributor.java %}
|
||||
```
|
||||
|
||||
### 13.4. Register the go to symbol contributor
|
||||
|
||||
## 13.4. Register the go to symbol contributor
|
||||
The `SimpleChooseByNameContributor` implementation is registered with the IntelliJ Platform using the `gotoSymbolContributor` extension point.
|
||||
```xml
|
||||
<gotoSymbolContributor implementation="com.simpleplugin.SimpleChooseByNameContributor"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<gotoSymbolContributor implementation="com.intellij.sdk.language.SimpleChooseByNameContributor"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 13.5. Run the project
|
||||
## 13.5. Run the project
|
||||
Rebuild the project, and run `simple_language` in a Development Instance.
|
||||
The IDE now supports navigating to a property definition by name pattern via **Navigate \| Symbol** action.
|
||||
|
||||
Now we can navigate to a property definition by name pattern via **Navigate \| Symbol** action.
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
@ -2,40 +2,42 @@
|
||||
title: 3. Grammar and Parser
|
||||
---
|
||||
|
||||
### 3.1. Define a token type
|
||||
|
||||
Create a file in the `com.simpleplugin.psi` package.
|
||||
In order for the IntelliJ Platform to parse a Simple language file, [tokens and elements](/reference_guide/custom_language_support/implementing_parser_and_psi.md) 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 in order to generate a parser.
|
||||
|
||||
* bullet item
|
||||
{:toc}
|
||||
|
||||
## 3.1. Define a Token Type
|
||||
Create `SimpleTokenType` in the `com.intellij.sdk.language.psi` package (see the `simple_language` code sample) by subclassing `IElementType`.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/psi/SimpleTokenType.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/psi/SimpleTokenType.java %}
|
||||
```
|
||||
|
||||
### 3.2. Define an element type
|
||||
|
||||
Create a file in the `com.simpleplugin.psi` package.
|
||||
|
||||
## 3.2. Define an Element Type
|
||||
Create the `SimpleElementType` in the `com.intellij.sdk.language.psi` package by subclassing `IElementType`.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/psi/SimpleElementType.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/psi/SimpleElementType.java %}
|
||||
```
|
||||
|
||||
### 3.3. Define grammar
|
||||
|
||||
Define a grammar for the properties language with */com/simpleplugin/Simple.bnf* file.
|
||||
|
||||
## 3.3. Define the Grammar
|
||||
Define a grammar for the Simple language in the `com/intellij/sdk/language/Simple.bnf` file.
|
||||
```java
|
||||
{
|
||||
parserClass="com.simpleplugin.parser.SimpleParser"
|
||||
parserClass="com.intellij.sdk.language.parser.SimpleParser"
|
||||
|
||||
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
|
||||
|
||||
psiClassPrefix="Simple"
|
||||
psiImplClassSuffix="Impl"
|
||||
psiPackage="com.simpleplugin.psi"
|
||||
psiImplPackage="com.simpleplugin.psi.impl"
|
||||
psiPackage="com.intellij.sdk.language.psi"
|
||||
psiImplPackage="com.intellij.sdk.language.psi.impl"
|
||||
|
||||
elementTypeHolderClass="com.simpleplugin.psi.SimpleTypes"
|
||||
elementTypeClass="com.simpleplugin.psi.SimpleElementType"
|
||||
tokenTypeClass="com.simpleplugin.psi.SimpleTokenType"
|
||||
elementTypeHolderClass="com.intellij.sdk.language.psi.SimpleTypes"
|
||||
elementTypeClass="com.intellij.sdk.language.psi.SimpleElementType"
|
||||
tokenTypeClass="com.intellij.sdk.language.psi.SimpleTokenType"
|
||||
|
||||
psiImplUtilClass="com.intellij.sdk.language.psi.impl.SimplePsiImplUtil"
|
||||
}
|
||||
|
||||
simpleFile ::= item_*
|
||||
@ -45,18 +47,17 @@ private item_ ::= (property|COMMENT|CRLF)
|
||||
property ::= (KEY? SEPARATOR VALUE?) | KEY
|
||||
```
|
||||
|
||||
As you see a properties file can contain properties, comments and line breaks.
|
||||
As shown, a properties file can contain properties, comments, and line breaks.
|
||||
|
||||
The grammar defines how flexible the support for a language can be.
|
||||
We specified that a property may have or may not have key and value.
|
||||
This lets the IDE still recognise incorrectly defined properties and provide corresponding code analysis and quick-fixes.
|
||||
The grammar defines the flexibility of the support for a language.
|
||||
The above grammar specifies that a property may have or may not have key and value.
|
||||
This allows the IntelliJ Platform to still recognise incorrectly defined properties and provide corresponding code analysis and quick-fixes.
|
||||
|
||||
Note that the `SimpleTypes` class in the `elementTypeHolderClass` field above specifies the name of a class that gets generated from the grammar, it doesn't exist at this point.
|
||||
Note that the `SimpleTypes` class in the `elementTypeHolderClass` field above specifies the name of a class that gets generated from the grammar; it doesn't exist at this point.
|
||||
|
||||
### 3.4. Generate a parser
|
||||
|
||||
Now when the grammar is defined we can generate a parser with PSI classes via *Generate Parser Code* from the context menu on *Simple.bnf* file.
|
||||
This will generate a parser and PSI elements in *gen* folder.
|
||||
## 3.4. Generate a Parser
|
||||
Now that the grammar is defined, generate a parser with PSI classes via **Generate Parser Code** from the context menu on the *Simple.bnf* file.
|
||||
This will generate a parser and PSI elements in the `/src/main/gen` folder of the project.
|
||||
Mark this folder as *Generated Sources Root* and make sure everything is compiled without errors.
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 184 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 195 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 135 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 193 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 125 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 352 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 318 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 156 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 110 KiB |
BIN
tutorials/custom_language_support/img/line_marker_location.png
Normal file
After Width: | Height: | Size: 278 KiB |
BIN
tutorials/custom_language_support/img/new_property.png
Normal file
After Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 242 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 144 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 190 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 264 KiB |
BIN
tutorials/custom_language_support/img/simple_named_element.png
Normal file
After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 153 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 110 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 135 KiB |
@ -2,63 +2,66 @@
|
||||
title: 2. Language and File Type
|
||||
---
|
||||
|
||||
The IntelliJ Platform [determines file type](/reference_guide/custom_language_support/registering_file_type.md) 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.
|
||||
The `LanguageFileType` is registered with the IntelliJ Platform in the plugin configuration file.
|
||||
|
||||
### 2.1. Define a language
|
||||
|
||||
Note the case of the name of the language - `Simple`.
|
||||
* bullet item
|
||||
{:toc}
|
||||
|
||||
## 2.1. Define the Language
|
||||
The language implemented in this tutorial is named "Simple" - note the case of the name.
|
||||
The `SimpleLanguage` class is defined in the `com.intellij.sdk.language` package of the `simple_language` code sample:
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleLanguage.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleLanguage.java %}
|
||||
```
|
||||
|
||||
### 2.2. Define an icon
|
||||
|
||||
Copy the
|
||||
[icon](https://raw.githubusercontent.com/JetBrains/intellij-sdk-docs/master/code_samples/simple_language_plugin/src/com/simpleplugin/icons/jar-gray.png)
|
||||
to **com.simpleplugin.icons** package.
|
||||
|
||||
## 2.2. Define an Icon
|
||||
The [icon](https://raw.githubusercontent.com/JetBrains/intellij-sdk-docs/master/code_samples/simple_language_plugin/src/com/simpleplugin/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`.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleIcons.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleIcons.java %}
|
||||
```
|
||||
|
||||
### 2.3. Define a file type
|
||||
|
||||
## 2.3. Define a FileType
|
||||
The Simple language file type is defined by subclassing `LanguageFileType`:
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleFileType.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleFileType.java %}
|
||||
```
|
||||
|
||||
### 2.4. Define a file type factory
|
||||
|
||||
> **NOTE** When targeting 2019.2 or later only, please see [2.5.B](#b-register-file-type-20192-or-later)
|
||||
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleFileTypeFactory.java %}
|
||||
```
|
||||
|
||||
### 2.5. Register the file type factory
|
||||
|
||||
In plugin.xml add:
|
||||
|
||||
## 2.4. Register the FileType Directly
|
||||
Direct registration is necessary when targeting version 2019.2 (and later) of the IntelliJ Platform.
|
||||
No `FileTypeFactory` is required.
|
||||
Instead, the file type is registered of file type is done via the `com.intellij.fileType` extension point in `plugin.xml`:
|
||||
```xml
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<fileTypeFactory implementation="com.simpleplugin.SimpleFileTypeFactory"/>
|
||||
<fileType name="Simple file" implementationClass="com.intellij.sdk.language.SimpleFileType" fieldName="INSTANCE"
|
||||
language="Simple" extensions="simple"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 2.5.B. Register file type (2019.2 or later)
|
||||
Skip to [section 2.6](#26-run-the-project).
|
||||
|
||||
When matching via file extension, pattern or exact file name, registration of file type should be done via `com.intellij.fileType` extension point instead of implementing dedicated `FileTypeFactory`.
|
||||
## 2.5. Register the FileType Using a Factory
|
||||
This pattern is necessary when targeting versions of the IntelliJ Platform prior to 2019.2
|
||||
|
||||
### 2.5.1 Define a FileType Factory
|
||||
First, define `SimpleFileTypeFactory` as a subclass of `FileTypeFactory`.
|
||||
```java
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleFileTypeFactory.java %}
|
||||
```
|
||||
|
||||
### 2.5.2 Register the FileType Factory
|
||||
The `FileTypeFactory` is registered with the IntelliJ Platform using the `com.intellij.openapi.fileTypes.FileTypeFactory` extension point in `plugin.xml`.
|
||||
```xml
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<fileType name="Simple file" implementationClass="com.simpleplugin.SimpleFileType" fieldName="INSTANCE"
|
||||
language="Simple" extensions="simple"/>
|
||||
<fileTypeFactory implementation="com.intellij.sdk.language.SimpleFileTypeFactory"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 2.6. Run the project
|
||||
## 2.6. Run the Project
|
||||
Create an empty file with the extension `\*.simple` and IntelliJ IDEA will automatically associate it with our language.
|
||||
Note the appearance of the Simple language file icon next to the `test.simple` file in the **Project Tool Window** and in the editor tab for the file.
|
||||
|
||||
Create a file with extension *.simple*
|
||||
and IntelliJ IDEA will automatically associate it with our language.
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
@ -2,57 +2,61 @@
|
||||
title: 4. Lexer and Parser Definition
|
||||
---
|
||||
|
||||
The lexer defines how the contents of a file is broken into tokens.
|
||||
The lexical analyzer defines how the [contents of a file are broken into tokens](/reference_guide/custom_language_support/implementing_lexer.md), which is the basis for supporting custom language features.
|
||||
The easiest way to create a lexer is to use [JFlex](https://jflex.de/)
|
||||
|
||||
### 4.1. Define a lexer
|
||||
|
||||
Define */com/simpleplugin/Simple.flex* file with rules for our lexer.
|
||||
* bullet item
|
||||
{:toc}
|
||||
|
||||
## 4.1. Define a Lexer
|
||||
Define a `Simple.flex` file with rules for the Simple language lexer, as demonstrated in `com.intellij.sdk.language.Simple.flex`.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/Simple.flex %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/Simple.flex %}
|
||||
```
|
||||
|
||||
### 4.2. Generate a lexer class
|
||||
## 4.2. Generate a Lexer Class
|
||||
Now generate a lexer class via **JFlex Generator** from the context menu on `Simple.flex` file.
|
||||
|
||||
Now we can generate a lexer class via *JFlex Generator* from the context menu on `Simple.flex` file.
|
||||
The Grammar-Kit plugin uses JFlex lexer generation.
|
||||
If you run it for the first time, it offers you to choose a folder to download the JFlex library and skeleton to.
|
||||
Choose the project root directory.
|
||||
When run for the first time, it prompts for a destination folder to download the JFlex library and skeleton.
|
||||
Choose the project root directory, for example `code_samples/simple_language`.
|
||||
|
||||
After that, the IDE generates the lexer: *com.simpleplugin.SimpleLexer*.
|
||||
After that, the IDE generates the lexer under the `gen` directory, for example in `simple_language/src/main/gen/com/intellij/sdk/language/SimpleLexer`.
|
||||
|
||||
### 4.3. Define an adapter
|
||||
See [Implementing Lexer](/reference_guide/custom_language_support/implementing_lexer.md) for more information about using _JFlex_ with the IntelliJ Platform.
|
||||
|
||||
## 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).
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleLexerAdapter.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleLexerAdapter.java %}
|
||||
```
|
||||
|
||||
### 4.4. Define a root file
|
||||
|
||||
Create the class in the `com.simpleplugin.psi` namespace.
|
||||
|
||||
## 4.4. Define a Root File
|
||||
The `SimpleFile` implementation is the top-level node of the [tree of `PsiElements`](/reference_guide/custom_language_support/implementing_parser_and_psi.md) for a Simple language file.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/psi/SimpleFile.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/psi/SimpleFile.java %}
|
||||
```
|
||||
|
||||
### 4.5. Define a parser definition
|
||||
|
||||
## 4.5. Define a Parser
|
||||
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/com/simpleplugin/SimpleParserDefinition.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleParserDefinition.java %}
|
||||
```
|
||||
|
||||
### 4.6. Register the parser definition
|
||||
|
||||
## 4.6. Register the Parser Definition
|
||||
Registering the parser definition in the `plugin.xml` file makes it available to the IntelliJ Platform.
|
||||
The `lang.parserDefinition` extension point is used for registration.
|
||||
For example, see `simple_language/src/main/resources/META-INF/plugin.xml`.
|
||||
```xml
|
||||
<lang.parserDefinition language="Simple" implementationClass="com.simpleplugin.SimpleParserDefinition"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<lang.parserDefinition language="Simple" implementationClass="com.intellij.sdk.language.SimpleParserDefinition"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 4.7. Run the project
|
||||
|
||||
Create a properties file with the following content:
|
||||
|
||||
```
|
||||
## 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:
|
||||
```text
|
||||
# You are reading the ".properties" entry.
|
||||
! The exclamation mark can also mark text as comments.
|
||||
website = http://en.wikipedia.org/
|
||||
@ -69,4 +73,4 @@ tab : \u0009
|
||||
|
||||
Now open the *PsiViewer* tool window and check how the lexer breaks the content of the file into tokens, and the parser parsed the tokens into PSI elements.
|
||||
|
||||

|
||||
{:width="900px"}
|
||||
|
@ -2,31 +2,37 @@
|
||||
title: 8. Line Marker Provider
|
||||
---
|
||||
|
||||
Line markers help to annotate any code with icons on the gutter.
|
||||
These icons may provide navigation to related code.
|
||||
Line markers help annotate code with icons on the gutter.
|
||||
These markers can provide navigation targets to related code.
|
||||
|
||||
### 8.1. Define a line marker provider
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
Let's annotate usages of our properties within Java code and provide navigation to the definition of these properties.
|
||||
## 8.1. Define a Line Marker Provider
|
||||
A line marker provider annotates usages of Simple language properties within Java code and provides navigation to the definition of these properties.
|
||||
The visual marker will be a Simple language icon in the gutter of the Editor window.
|
||||
|
||||
The Simple language marker provider is subclassed from [`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):
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleLineMarkerProvider.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleLineMarkerProvider.java %}
|
||||
```
|
||||
|
||||
## More technical details for implementers
|
||||
|
||||
* Please return line marker info for exact element you were asked for.
|
||||
For example, do not return class marker info if `getLineMarkerInfo()` was called for a method.
|
||||
|
||||
* Please return relevant line marker info for as small element as possible.
|
||||
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 is a name of this method.
|
||||
|
||||
### Even more technical details:
|
||||
|
||||
What happens when `LineMarkerProvider` returns something for too big PsiElement?
|
||||
## 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.
|
||||
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.
|
||||
|
||||
{:width="900px"}
|
||||
|
||||
What happens when a `LineMarkerProvider` returns marker information for a `PsiElement` that is a higher node in the PSI tree?
|
||||
For example, if `MyWrongLineMarkerProvider()` erroneously returns a `PsiMethod` instead of a `PsiIdentifier` element:
|
||||
```java
|
||||
public class MyLineMarkerProvider implements LineMarkerProvider {
|
||||
public class MyWrongLineMarkerProvider implements LineMarkerProvider {
|
||||
public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) {
|
||||
if (element instanceof PsiMethod) return new LineMarkerInfo(element, ...);
|
||||
return null;
|
||||
@ -34,25 +40,20 @@ public class MyLineMarkerProvider implements LineMarkerProvider {
|
||||
}
|
||||
```
|
||||
|
||||
Inspection (specifically, [`LineMarkersPass`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java)) for performance reasons queries all [`LineMarkerProviders`](upsource:///platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerProviders.java) in two passes:
|
||||
The consequences of the `MyWrongLineMarkerProvider()` implementation have to do with how the IntelliJ Platform performs inspections.
|
||||
For performance reasons, inspection, and specifically the [`LineMarkersPass`](upsource:///platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java) queries all [`LineMarkerProviders`](upsource:///platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerProviders.java) in two phases:
|
||||
* The first pass is for all elements visible in the Editor window,
|
||||
* The second pass is for the rest of the elements in the file.
|
||||
|
||||
* first pass for all elements in visible area
|
||||
|
||||
* second pass for all the rest elements
|
||||
|
||||
If providers return nothing for either area, its line markers are cleared.
|
||||
So if e.g. a method is half-visible (its name is visible but part of its body isn't) and
|
||||
some poorly written [`LineMarkerProvider`](upsource:///platform/lang-api/src/com/intellij/codeInsight/daemon/LineMarkerProvider.java) returned info for the `PsiMethod` instead of `PsiIdentifier` then:
|
||||
|
||||
* the first pass removes line marker info because whole `PsiMethod` is not visible.
|
||||
|
||||
* the second pass tries to add line marker info back because `LineMarkerProvider` is called for the `PsiMethod` at last.
|
||||
|
||||
As a result, line marker icon would blink annoyingly.
|
||||
To fix this, rewrite `LineMarkerProvider` to return info for `PsiIdentifier` instead of `PsiMethod`:
|
||||
If providers return nothing for either area, the line markers are 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`.
|
||||
|
||||
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:
|
||||
```java
|
||||
public class MyLineMarkerProvider implements LineMarkerProvider {
|
||||
public class MyCorrectLineMarkerProvider implements LineMarkerProvider {
|
||||
public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) {
|
||||
if (element instanceof PsiIdentifier && element.getParent() instanceof PsiMethod) return new LineMarkerInfo(element, ...);
|
||||
return null;
|
||||
@ -60,14 +61,17 @@ public class MyLineMarkerProvider implements LineMarkerProvider {
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2. Register the line marker provider
|
||||
|
||||
## 8.3. Register the Line Marker Provider
|
||||
The `SimpleLineMarkerProvider` implementation is registered with the IntelliJ Platform using the `codeInsight.lineMarkerProvider` extension point.
|
||||
```xml
|
||||
<codeInsight.lineMarkerProvider language="JAVA" implementationClass="com.simpleplugin.SimpleLineMarkerProvider"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<codeInsight.lineMarkerProvider language="JAVA" implementationClass="com.intellij.sdk.language.SimpleLineMarkerProvider"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 8.3. Run the project
|
||||
|
||||
Now you see the icon on the gutter and can navigate to the property definition.
|
||||
## 8.4. Run the Project
|
||||
Run the `simple_language` plugin in a Development Instance and open the [Test file](/tutorials/custom_language_support/annotator.md#run-the-project).
|
||||
Now the icon appears next to line 3 on the gutter.
|
||||
A user can click on the icon to navigate to the property definition.
|
||||
|
||||

|
||||
|
@ -2,24 +2,19 @@
|
||||
title: 6. PSI Helpers and Utilities
|
||||
---
|
||||
|
||||
Helper classes and utilities can be embedded in the code generated by Grammar-Kit.
|
||||
|
||||
### 6.1. Define helper methods for generated PSI elements
|
||||
|
||||
If we want to have custom methods in PSI classes we need to define them separately and ask Grammar-Kit to embed them into generated code.
|
||||
|
||||
Let's define a utility class with these helper methods.
|
||||
* bullet item
|
||||
{: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.
|
||||
Define a utility class with these helper methods:
|
||||
```java
|
||||
package com.simpleplugin.psi.impl;
|
||||
package com.intellij.sdk.language.psi.impl;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.psi.*;
|
||||
import com.simpleplugin.SimpleIcons;
|
||||
import com.simpleplugin.psi.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import com.intellij.sdk.language.psi.*;
|
||||
|
||||
public class SimplePsiImplUtil {
|
||||
public static String getKey(SimpleProperty element) {
|
||||
@ -31,7 +26,7 @@ public class SimplePsiImplUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String getValue(SimpleProperty element) {
|
||||
ASTNode valueNode = element.getNode().findChildByType(SimpleTypes.VALUE);
|
||||
if (valueNode != null) {
|
||||
@ -43,13 +38,12 @@ public class SimplePsiImplUtil {
|
||||
}
|
||||
```
|
||||
|
||||
Note that the `SimpleProperty` interface referenced in the code above is generated by the parser. Also note that the `element.getKey` method used in `getPresentableText` will not be defined - it's a method generated by the parser, which we'll fix below.
|
||||
The parser generates the `SimpleProperty` interface referenced in the code above.
|
||||
|
||||
### 6.2. Update grammar and regenerate the parser
|
||||
|
||||
Now we tell to use this utility class in the grammar file via `psiImplUtilClass` attribute.
|
||||
|
||||
To tell which methods for which PSI classes must be used we specify methods for particular rule.
|
||||
## 6.2. Update Grammar and Regenerate the Parser
|
||||
Now the utility class is added to the grammar file via the `psiImplUtilClass` attribute.
|
||||
Add methods for a particular rule to specify which one should be used for PSI classes.
|
||||
Compare the last line of the grammar below to the [previous definition](/tutorials/custom_language_support/grammar_and_parser.md#33-define-the-grammar).
|
||||
|
||||
```java
|
||||
{
|
||||
@ -76,13 +70,12 @@ private item_ ::= (property|COMMENT|CRLF)
|
||||
property ::= (KEY? SEPARATOR VALUE?) | KEY {methods=[getKey getValue]}
|
||||
```
|
||||
|
||||
After we made our changes to the grammar we can regenerate the parser and PSI classes.
|
||||
|
||||
### 6.3. Define a utility to search properties
|
||||
|
||||
Now we need a utility class to search PSI elements for defined properties over the project.
|
||||
We will use this utility later when implementing code assistance.
|
||||
After making changes to the grammar, regenerate the parser and PSI classes.
|
||||
|
||||
## 6.3. Define a Utility to Search Properties
|
||||
Create a utility class to search PSI elements for defined properties over the project.
|
||||
This utility will be used later when implementing [code completion](https://www.jetbrains.com/help/idea/auto-completing-code.html).
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleUtil.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleUtil.java %}
|
||||
```
|
||||
|
||||
|
@ -2,35 +2,47 @@
|
||||
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).
|
||||
For the Simple language, this tutorial adds a quick fix that helps to define an unresolved property from its usage.
|
||||
|
||||
A quick fix allows to apply an automatic changes to the code via **Show Intention Actions** (Alt + Enter).
|
||||
|
||||
Let's add a quick fix which helps to define an unresolved property from its usage.
|
||||
|
||||
### 18.1. Update the element factory
|
||||
* 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.
|
||||
A new overload of `createProperty()` creates a new `key`-`value` pair for Simple language.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/psi/SimpleElementFactory.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/psi/SimpleElementFactory.java %}
|
||||
```
|
||||
|
||||
### 18.2. Define an intention action
|
||||
|
||||
The quick fix will create a property in the file chosen by user, and navigate to this property after creation.
|
||||
|
||||
## 18.2. Define an Intention Action
|
||||
The `SimpleCreatePropertyQuickFix` will create 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`](/code_samples/conditional_operator_intention).
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/CreatePropertyQuickFix.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleCreatePropertyQuickFix.java %}
|
||||
```
|
||||
|
||||
### 18.3. Update the annotator
|
||||
|
||||
Note the call to `registerFix`.
|
||||
|
||||
## 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.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleAnnotator.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleAnnotator.java %}
|
||||
```
|
||||
|
||||
### 18.4. Run the project
|
||||
## 18.4. Run the project
|
||||
Open the test [Java file](/tutorials/custom_language_support/annotator.md#run-the-project) in an IDE Development Instance running the `simple_language` plugin.
|
||||
|
||||
Now let's try to use a property which is not defined yet.
|
||||
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".
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
||||
The IDE will open the `test.simple` file and add `website.url` as a new key.
|
||||
Add the new value `jetbrains.com` for the new `website.url` key.
|
||||
|
||||
{:width="800px"}
|
||||
|
||||
Now switch back to the Java file; the new key is highlighted as valid.
|
@ -2,25 +2,24 @@
|
||||
title: 10. Reference Contributor
|
||||
---
|
||||
|
||||
|
||||
References is one of the most important and tricky parts in the implementation of a custom language support.
|
||||
The [References functionality](/reference_guide/custom_language_support/references_and_resolve.md) is one of the most important parts in the implementation of custom language support.
|
||||
Resolving references means the ability to go from the usage of an element to its declaration, completion, rename refactoring, find usages, etc.
|
||||
|
||||
**Every element which can be renamed or referenced needs to implement `com.intellij.psi.PsiNamedElement` interface.**
|
||||
> **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.
|
||||
|
||||
### 10.1. Define a base named element class
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/psi/SimpleNamedElement.java %}
|
||||
```
|
||||
### 10.1. Define a Named Element Class
|
||||
The simplified class diagram below shows how the Simple language fulfills the need to implement `PsiNamedElement`.
|
||||
The `SimpleNamedElement` interface is subclassed from [`PsiNameIdentifierOwner`]().
|
||||
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/com/simpleplugin/psi/impl/SimpleNamedElementImpl.java %}
|
||||
```
|
||||
|
||||
### 10.2. Define helper methods for generated PSI elements
|
||||
|
||||
Since we need to implement new methods in PSI class, we should define them in the `SimplePsiImplUtil` class:
|
||||
{:width="400px"}
|
||||
|
||||
## 10.2. Define Helper Methods for Generated PSI Elements
|
||||
Modify `SimplePsiImplUtil` to support new methods that will get added to the PSI class for Simple language.
|
||||
Note that `SimpleElementFactory` isn't defined until the [next step](#103-define-an-element-factory), so for now it shows as an error.
|
||||
|
||||
```java
|
||||
public class SimplePsiImplUtil {
|
||||
@ -55,89 +54,71 @@ public class SimplePsiImplUtil {
|
||||
}
|
||||
```
|
||||
|
||||
Note that the `SimpleElementFactory` class will show as an error. We'll create it next.
|
||||
|
||||
### 10.3. Define an element factory
|
||||
|
||||
## 10.3. Define an Element Factory
|
||||
The `SimpleElementFactory` provides methods for creating `SimpleFile`.
|
||||
```java
|
||||
package com.simpleplugin.psi;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.simpleplugin.SimpleFileType;
|
||||
|
||||
public class SimpleElementFactory {
|
||||
public static SimpleProperty createProperty(Project project, String name) {
|
||||
final SimpleFile file = createFile(project, name);
|
||||
return (SimpleProperty) file.getFirstChild();
|
||||
}
|
||||
|
||||
public static SimpleFile createFile(Project project, String text) {
|
||||
String name = "dummy.simple";
|
||||
return (SimpleFile) PsiFileFactory.getInstance(project).
|
||||
createFileFromText(name, SimpleFileType.INSTANCE, text);
|
||||
}
|
||||
}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/psi/SimpleElementFactory.java %}
|
||||
```
|
||||
|
||||
### 10.4. Update grammar and regenerate the parser
|
||||
|
||||
Now we need to make corresponding changes to the grammar file and regenerate parser and PSI classes.
|
||||
|
||||
## 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 line below.
|
||||
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="com.simpleplugin.psi.impl.SimpleNamedElementImpl"
|
||||
implements="com.simpleplugin.psi.SimpleNamedElement" methods=[getKey getValue getName setName getNameIdentifier]}
|
||||
property ::= (KEY? SEPARATOR VALUE?) | KEY {mixin="com.intellij.sdk.language.psi.impl.SimpleNamedElementImpl"
|
||||
implements="com.intellij.sdk.language.psi.SimpleNamedElement" methods=[getKey getValue getName setName getNameIdentifier]}
|
||||
```
|
||||
|
||||
Don't forget to regenerate the parser! Right click on the `Simple.bnf` file and select _Generate Parser Code_.
|
||||
|
||||
### 10.5. Define a reference
|
||||
|
||||
Now we need to define a reference class to resolve a property from it's usage.
|
||||
|
||||
## 10.5. Define a Reference
|
||||
Now define a reference class to resolve a property from its usage.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleReference.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleReference.java %}
|
||||
```
|
||||
|
||||
### 10.6. Define a reference contributor
|
||||
|
||||
A reference contributor allows you to provide references from elements in other languages such as Java to elements in your language.
|
||||
Let's contribute a reference to each usage of a property.
|
||||
|
||||
## 10.6. Define a Reference Contributor
|
||||
A reference contributor allows the `simple_language` plugin to provide references to Simple language from elements in other languages such as Java.
|
||||
Create `SimpleReferenceContributor` by subclassing [`PsiReferenceContributor`](upsource:///platform/core-api/src/com/intellij/psi/PsiReferenceContributor.java).
|
||||
Contribute a reference to each usage of a property:
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleReferenceContributor.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleReferenceContributor.java %}
|
||||
```
|
||||
|
||||
### 10.7. Register the reference contributor
|
||||
|
||||
## 10.7. Register the Reference Contributor
|
||||
The `SimpleReferenceContributor` implementation is registered with the IntelliJ Platform using the `psi.referenceContributor` extension point.
|
||||
```xml
|
||||
<psi.referenceContributor implementation="com.simpleplugin.SimpleReferenceContributor"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<psi.referenceContributor implementation="com.intellij.sdk.language.SimpleReferenceContributor"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 10.8. Run the project
|
||||
## 10.8. Run the Project
|
||||
Rebuild the project, and run `simple_language` in a Development Instance.
|
||||
The IDE now resolves the property and provides [completion](https://www.jetbrains.com/help/idea/auto-completing-code.html#basic_completion) suggestions:
|
||||
|
||||
As you see the IDE now resolves the property and provides completion.
|
||||
{:width="800px"}
|
||||
|
||||

|
||||
The [Rename refactoring](https://www.jetbrains.com/help/idea/rename-refactorings.html#invoke-rename-refactoring) functionality is now available from definition and usages.
|
||||
|
||||
*Rename* refactoring available from definition and usages.
|
||||
|
||||

|
||||
|
||||
### 10.9. Define a refactoring support provider
|
||||
|
||||
To allow in-place refactoring we should specify it explicitly in a refactoring support provider.
|
||||
{:width="800px"}
|
||||
|
||||
## 10.9. Define a Refactoring Support Provider
|
||||
To allow in-place refactoring it is specified explicitly in a refactoring support provider.
|
||||
Create `SimpleRefactoringSupportProvider` by subclassing [`RefactoringSupportProvider`](upsource:///platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java)
|
||||
As long as an element is a `SimpleProperty` it is allowed to be refactored:
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleRefactoringSupportProvider.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleRefactoringSupportProvider.java %}
|
||||
```
|
||||
|
||||
### 10.10. Register the refactoring support provider
|
||||
|
||||
## 10.10. Register the Refactoring Support Provider
|
||||
The `SimpleRefactoringSupportProvider` implementation is registered with the IntelliJ Platform using the `lang.refactoringSupport` extension point.
|
||||
```xml
|
||||
<lang.refactoringSupport language="Simple" implementationClass="com.simpleplugin.SimpleRefactoringSupportProvider"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<lang.refactoringSupport language="Simple" implementationClass="com.intellij.sdk.language.SimpleRefactoringSupportProvider"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 10.11. Run the project
|
||||
## 10.11. Run the Project
|
||||
Rebuild the project, and run `simple_language` in a Development Instance.
|
||||
The IDE now supports [refactoring](https://www.jetbrains.com/help/idea/rename-refactorings.html) suggestions:
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
@ -2,33 +2,46 @@
|
||||
title: 14. Structure View Factory
|
||||
---
|
||||
|
||||
The [structure view](/reference_guide/custom_language_support/structure_view.md) in the IntelliJ Platform-based IDE can be customized for a specific file type, including Simple language.
|
||||
Creating a structure view factory allows showing the structure of any file in a **Structure** tool window for easy navigation between items.
|
||||
|
||||
A structure view factory allows to show the structure of any file in a *Structure* tool window for easy navigation between items.
|
||||
|
||||
### 14.1. Define a structure view factory
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
## 14.1. Define a Structure View Factory
|
||||
The structure view factory implements [`PsiStructureViewFactory`](upsource:///community/platform/editor-ui-api/src/com/intellij/lang/PsiStructureViewFactory.java).
|
||||
The `getStructureViewBuilder()` implementation reuses the IntelliJ Platform class [`TreeBasedStructureViewBuilder`](upsource:///community/platform/editor-ui-api/src/com/intellij/ide/structureView/TreeBasedStructureViewBuilder.java).
|
||||
At this point the project will not compile until `SimpleStructureViewModel` is implemented below.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewFactory.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleStructureViewFactory.java %}
|
||||
```
|
||||
|
||||
### 14.2. Define a structure view model
|
||||
|
||||
## 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.
|
||||
It also extends [`StructureViewModelBase`](upsource:///community/platform/editor-ui-api/src/com/intellij/ide/structureView/StructureViewModelBase.java), an implementation that links the model to a text editor.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewModel.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleStructureViewModel.java %}
|
||||
```
|
||||
|
||||
### 14.3. Define a structure view element
|
||||
|
||||
## 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.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewElement.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleStructureViewElement.java %}
|
||||
```
|
||||
|
||||
### 14.4. Register the structure view factory
|
||||
|
||||
## 14.4. Register the Structure View Factory
|
||||
The `SimpleStructureViewFactory` implementation is registered with the IntelliJ Platform in `plugin.xml` using the `lang.psiStructureViewFactory` extension point.
|
||||
```xml
|
||||
<lang.psiStructureViewFactory language="Simple" implementationClass="com.simpleplugin.SimpleStructureViewFactory"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<lang.psiStructureViewFactory language="Simple" implementationClass="com.intellij.sdk.language.SimpleStructureViewFactory"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 14.5. Run the project
|
||||
## 14.5. Run the Project
|
||||
Rebuild the project, and run `simple_language` in a Development Instance.
|
||||
Open the `test.simple` file and choose **View \| Tool Windows \| Structure**.
|
||||
The IDE now supports a structure view of the Simple language:
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
@ -2,41 +2,58 @@
|
||||
title: 5. Syntax Highlighter and Color Settings Page
|
||||
---
|
||||
|
||||
The first level of [syntax highlighting](/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md#lexer) is based on the lexer output, and is provided by `SyntaxHighlighter`.
|
||||
A plugin can also define [color settings](/reference_guide/custom_language_support/syntax_highlighting_and_error_highlighting.md#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` code sample.
|
||||
|
||||
### 5.1. Define a syntax highlighter
|
||||
* bullet list
|
||||
{:toc}
|
||||
|
||||
## 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.
|
||||
For the Simple language, only one scheme is defined.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleSyntaxHighlighter.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleSyntaxHighlighter.java %}
|
||||
```
|
||||
|
||||
### 5.2. Define a syntax highlighter factory
|
||||
|
||||
### 5.2. Define a Syntax Highlighter Factory
|
||||
The factory provides a standard way for the IntelliJ Platform to instantiate the syntax highlighter for Simple language files.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleSyntaxHighlighterFactory.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleSyntaxHighlighterFactory.java %}
|
||||
```
|
||||
|
||||
### 5.3. Register the syntax highlighter factory
|
||||
|
||||
### 5.3. Register the Syntax Highlighter Factory
|
||||
The factory is registered with the IntelliJ Platform using the plugin configuration file.
|
||||
```xml
|
||||
<lang.syntaxHighlighterFactory language="Simple" implementationClass="com.simpleplugin.SimpleSyntaxHighlighterFactory"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<lang.syntaxHighlighterFactory language="Simple" implementationClass="com.intellij.sdk.language.SimpleSyntaxHighlighterFactory"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 5.4. Run the project
|
||||
### 5.4. Run the Project
|
||||
Open the example Simple Language [properties file ](/tutorials/custom_language_support/lexer_and_parser_definition.md#47-run-the-project) in the IDE Development Instance.
|
||||
The colors for Simple Language Key, Separator, and Value highlighting default to the IDE _Language Defaults_ for Keyword, Braces and Operators, and String, respectively.
|
||||
|
||||

|
||||
|
||||
### 5.5. Define a color settings page
|
||||
{:width="800px"}
|
||||
|
||||
## 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` extends `ColorSettingsPage`.
|
||||
```java
|
||||
{% include /code_samples/simple_language_plugin/src/com/simpleplugin/SimpleColorSettingsPage.java %}
|
||||
{% include /code_samples/simple_language/src/main/java/com/intellij/sdk/language/SimpleColorSettingsPage.java %}
|
||||
```
|
||||
|
||||
### 5.6. Register the color settings page
|
||||
|
||||
### 5.6. Register the Color Settings Page
|
||||
The settings page for Simple language colors is registered in the plugin configuration file as an extension.
|
||||
```xml
|
||||
<colorSettingsPage implementation="com.simpleplugin.SimpleColorSettingsPage"/>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<colorSettingsPage implementation="com.intellij.sdk.language.SimpleColorSettingsPage"/>
|
||||
</extensions>
|
||||
```
|
||||
|
||||
### 5.7. Run the project
|
||||
In the IDE Development Instance, open the Simple language highlight settings page: **Preferences/Settings \| Editor \| Color Scheme \| Simple**.
|
||||
Each color initially inherits from a _Language Defaults_ value.
|
||||
|
||||

|
||||
{:width="800px"}
|
||||
|
@ -2,14 +2,11 @@
|
||||
title: Custom Language Support Tutorial
|
||||
---
|
||||
|
||||
In this tutorial we will add support for
|
||||
[.properties](https://en.wikipedia.org/wiki/.properties)
|
||||
language and its usages within Java code.
|
||||
|
||||
The final code can be found in the [SamplePlugin repo on GitHub](https://github.com/JetBrains/intellij-sdk-docs/tree/master/code_samples/simple_language_plugin).
|
||||
|
||||
This a step-by-step tutorial and it requires performing every step:
|
||||
|
||||
In this tutorial we will add support for a [.properties](https://en.wikipedia.org/wiki/.properties) language and its usages within Java code.
|
||||
IntelliJ Platform support for custom languages is discussed in more depth in the [Custom Language](/reference_guide/custom_language_support.md) section.
|
||||
|
||||
The example plugin used in this tutorial is the `simple_language` code sample.
|
||||
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)
|
||||
* [3. Grammar and Parser](custom_language_support/grammar_and_parser.md)
|
||||
|