diff --git a/topics/intro/content_updates.md b/topics/intro/content_updates.md
index 7f8ddbef8..c13977fad 100644
--- a/topics/intro/content_updates.md
+++ b/topics/intro/content_updates.md
@@ -9,6 +9,12 @@ See [GitHub Changelog](https://github.com/JetBrains/intellij-sdk-docs/commits/ma
## 2021
+### November-21
+
+Language Injection
+: Add [Language Injection](language_injection.md) section that shows how the IntelliJ Platform handles different languages within the same source file.
+
+
### September-21
IDE Infrastructure
diff --git a/topics/reference_guide/custom_language_support/language_injection.md b/topics/reference_guide/custom_language_support/language_injection.md
index 74b396b5b..087927374 100644
--- a/topics/reference_guide/custom_language_support/language_injection.md
+++ b/topics/reference_guide/custom_language_support/language_injection.md
@@ -1,6 +1,6 @@
[//]: # (title: Language Injection)
-
+
Language injection is the way the IntelliJ Platform handles different languages within the same source file. Well-known examples are:
@@ -12,13 +12,13 @@ Injected code is always bound to a specific context that depends on the surround
-
+
-
+
-
+
@@ -46,7 +46,7 @@ The injections shown are configured through XML files and loaded automatically.
Let’s take a look at the Java `String.matches()` method that injects the RegExp language into the string of the first argument.
In the IntelliLang settings, it is defined as one possible injection in Java code.
-
+{border-effect="line"}
Double-clicking on this entry shows the exact context where a RegExp can be injected, and `String.matches()` is one of several possibilities.
On the plugin side, these entries are defined in the file [`javaInjections.xml`](upsource:///plugins/IntelliLang/java-support/resources/javaInjections.xml):
@@ -55,7 +55,12 @@ On the plugin side, these entries are defined in the file [`javaInjections.xml`]
String (java.lang)
...
-
+
```
@@ -107,13 +112,13 @@ For instance, injecting SQLite into Python code is specified by the following op
Inside an injection, the following tags can be used:
-| XML Tag | Description |
-|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `` | A short name for the injection. |
-| `` | The element pattern that defines where an injection will take place. The content is wrapped in `![CDATA[...]]`. |
-| `` and `` | Static content that is wrapped around the injected code, e.g., to make it a valid expression. For example, to a CSS color specification inside a string, it can be wrapped with the prefix `div { color:` and the suffix `;}` to make it a valid CSS expression. |
-| `` | A regex for the content that specifies when this injection should be applied. |
-| `` | A regex for the content that specifies when this injection should not be applied. |
+| XML Tag | Description |
+|---------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `` | A short name for the injection. |
+| `` | The element pattern that defines where an injection will take place. The content is wrapped in `![CDATA[...]]`. |
+| `` and `` | Static content that is wrapped around the injected code, e.g., to make it a valid expression. For example, to a CSS color specification inside a string, it can be wrapped with the prefix `div { color:` and the suffix `;}` to make it a valid CSS expression. |
+| `` | A regex for the content that specifies when this injection should be applied. Regex groups can specify the text range of the injection (e.g. `^javascript:(.+)`, see [`xmlInjections-html.xml`](upsource:///plugins/IntelliLang/xml-support/resources/xmlInjections-html.xml)). |
+| `` | A regex for the content that specifies when this injection should not be applied. |
#### Create an XML File to Load the Configuration
@@ -134,7 +139,9 @@ The injections are an optional dependency that only work when IntelliLang is ena
Therefore, you load the configuration optionally in your main plugin.xml:
````xml
-org.intellij.intelliLang
+
+ org.intellij.intelliLang
+
````
## LanguageInjectionContributor and LanguageInjectionPerformer
@@ -149,10 +156,12 @@ public final class MyConfigInjector implements LanguageInjectionContributor {
public Injection getInjection(@NotNull PsiElement context) {
if (!isConfigPlace(context)) return null;
if (shouldInjectYaml(context)) {
- return new SimpleInjection(YAMLLanguage.INSTANCE.getID(), "", "", null);
+ return new SimpleInjection(
+ YAMLLanguage.INSTANCE.getID(), "", "", null);
}
else if (shouldInjectJSON(context)) {
- return new SimpleInjection(JsonLanguage.INSTANCE.getID(), "", "", null);
+ return new SimpleInjection(
+ JsonLanguage.INSTANCE.getID(), "", "", null);
}
return null;
}
@@ -162,7 +171,9 @@ public Injection getInjection(@NotNull PsiElement context) {
Register the implementation in your plugin.xml:
```xml
-
+
```
If you want more control over how the injection should be done then implement the `com.intellij.languageInjectionPerformer` EP which allows for complex language injections, e.g. for concatenation or interpolation of strings.
@@ -184,11 +195,15 @@ Plugin authors need to implement `getLanguagesToInject()` to provide a list of p
For example, to inject regular expressions into Java string literal, you can override this method with something similar to this:
```java
-class MyRegExpToJavaInjector implements MultiHostInjector {
- void getLanguagesToInject(MultiHostRegistrar registrar, PsiElement context) {
- if (context instanceof PsiLiteralExpression && looksLikeAGoodPlaceToInject(context)) {
- registrar.startInjecting(REGEXP_LANG)
- .addPlace(null,null,context,innerRangeStrippingQuotes(context));
+public class MyRegExpToJavaInjector implements MultiHostInjector {
+ public void getLanguagesToInject(
+ MultiHostRegistrar registrar, PsiElement context) {
+ if (context instanceof PsiLiteralExpression &&
+ looksLikeAGoodPlaceToInject(context)) {
+ registrar
+ .startInjecting(REGEXP_LANG)
+ .addPlace(null,null,
+ context,innerRangeStrippingQuotes(context));
}
}
}
@@ -198,7 +213,12 @@ A more complex example is when you need to inject into several fragments at once
For example, if we have an XML-based DSL:
```xml
-fooSystem.out.println(42);
+
+
+ foo
+ System.out.println(42);
+
+
```
which should be converted to the equivalent Java code:
@@ -210,13 +230,19 @@ class MyDsl { void foo() { System.out.println(42); } }
Here, we need to inject Java into several places at once, i.e. method name and its body:
```java
-class MyBizarreDSLInjector implements MultiHostInjector {
- void getLanguagesToInject(MultiHostRegistrar registrar, PsiElement context) {
+public class MyBizarreDSLInjector implements MultiHostInjector {
+ public void getLanguagesToInject(
+ MultiHostRegistrar registrar, PsiElement context) {
if (isMethodTag(context)) {
registrar.startInjecting(JavaLanguage.INSTANCE);
- // construct class header, method header, inject method name, append code block start
- registrar.addPlace("class MyDsl { void ", "() {", context, rangeForMethodName(context));
- // inject method body, append closing braces to form a valid Java class structure
+
+ // construct class header, method header,
+ // inject method name, append code block start
+ registrar.addPlace("class MyDsl { void ", "() {",
+ context, rangeForMethodName(context));
+
+ // inject method body, append closing braces
+ // to form a valid Java class structure
registrar.addPlace(null, "}}", context, rangeForBody(context));
registrar.doneInjecting();
}