Fix code samples in "Language Injection" article (#804)

- `SimpleInjection` now takes `Language` as first parameter, not `String`
- `.doneInjecting()` should be called at the end of injecting
- Added information about the `elementsToInjectIn()` method, which also needs to be implemented.
- added `plugin.xml` example in `MultiHostInjector` for consistency
This commit is contained in:
Makhnev Petr 2022-07-13 18:42:52 +03:00 committed by GitHub
parent 635bf94659
commit c46dc50e37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -168,14 +168,17 @@ For instance, if you want to inject a YAML or JSON to a literal language dependi
```java ```java
public final class MyInjector implements LanguageInjectionContributor { public final class MyInjector implements LanguageInjectionContributor {
public Injection getInjection(@NotNull PsiElement context) { @Override
public @Nullable Injection getInjection(@NotNull PsiElement context) {
if (!isConfigPlace(context)) return null; if (!isConfigPlace(context)) return null;
if (shouldInjectYaml(context)) { if (shouldInjectYaml(context)) {
return new SimpleInjection( return new SimpleInjection(
YAMLLanguage.INSTANCE.getID(), "", "", null); YAMLLanguage.INSTANCE, "", "", null
);
} else if (shouldInjectJSON(context)) { } else if (shouldInjectJSON(context)) {
return new SimpleInjection( return new SimpleInjection(
JsonLanguage.INSTANCE.getID(), "", "", null); JsonLanguage.INSTANCE, "", "", null
);
} }
return null; return null;
} }
@ -210,21 +213,36 @@ The method `performInjection()` does the actual injection into the context PSI e
[`MultiHostInjector`](upsource:///platform/core-api/src/com/intellij/lang/injection/MultiHostInjector.java) registered in `com.intellij.multiHostInjector` EP is a very low-level API, but it gives plugin authors the most freedom. [`MultiHostInjector`](upsource:///platform/core-api/src/com/intellij/lang/injection/MultiHostInjector.java) registered in `com.intellij.multiHostInjector` EP is a very low-level API, but it gives plugin authors the most freedom.
It performs language injection inside other PSI elements, e.g. inject SQL inside an XML tag text or inject regular expressions into Java string literals. It performs language injection inside other PSI elements, e.g. inject SQL inside an XML tag text or inject regular expressions into Java string literals.
Plugin authors need to implement `getLanguagesToInject()` to provide a list of places to inject a language to. Plugin authors need to implement `getLanguagesToInject()` to provide a list of places to inject a language, and `elementsToInjectIn()` to return a list of elements to inject.
For example, to inject regular expressions into Java string literal, you can override this method with something similar to this:
For example, inject regular expressions into Java string literal:
```java ```java
public class MyRegExpToJavaInjector implements MultiHostInjector { public class MyRegExpToJavaInjector implements MultiHostInjector {
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar,
@NotNull PsiElement context) { @NotNull PsiElement context) {
if (context instanceof PsiLiteralExpression && shouldInject(context)) { if (context instanceof PsiLiteralExpression && shouldInject(context)) {
registrar registrar
.startInjecting(REGEXP_LANG) .startInjecting(RegExpLanguage.INSTANCE)
.addPlace(null, null, context, innerRangeStrippingQuotes(context)); .addPlace(null, null, context, innerRangeStrippingQuotes(context))
.doneInjecting();
} }
} }
@Override
public @NotNull List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
return List.of(PsiLiteralExpression.class);
} }
}
```
Register the implementation in your <path>plugin.xml</path>:
```xml
<multiHostInjector
implementation="MyRegExpToJavaInjector"/>
``` ```
A more complex example is when you need to inject into several fragments at once. A more complex example is when you need to inject into several fragments at once.
@ -250,6 +268,7 @@ Here, we need to inject Java into several places at once, i.e. method name and i
```java ```java
public class MyBizarreDSLInjector implements MultiHostInjector { public class MyBizarreDSLInjector implements MultiHostInjector {
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar,
@NotNull PsiElement context) { @NotNull PsiElement context) {
if (isMethodTag(context)) { if (isMethodTag(context)) {