CDATA inside MultiHostInjector Follow
Hello,
I already asked the following question on slack, but did not get an answer yet (https://jetbrains-platform.slack.com/archives/C5U8BM1MK/p1636443212249900). Maybe someone here knows a solution.
--
I've got an XML file which may contain SQL inside a specific tag. I would like to inject SQL Language into the contents of the tag, so that code completion etc is available. For now it seems to work properly using a MultiHostInjector
. However the content of that tag may also be wrapped inside a CDATA-wrapper. I've already modified the injected TextRange to match only the text inside the CDATA-section. However when I now use the function to edit the fragment inside a separate editor ("Edit generic SQL fragment") the CDATA part is removed as soon as I start typing. Any ideas?
Sample XML file:
<sql> <![CDATA[ SELECT * FROM FOO ]]> </sql>
Here is my code in my plugin:
public class MyCustomSQLLanguageInjector implements MultiHostInjector {
private static final String CDATA_START = "<![CDATA[";
private static final String CDATA_END = "]]>";
@Override
public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
PsiFile psiFile = context.getContainingFile().getOriginalFile();
if ( (psiFile.getName().equals("default.xml")) &&
(psiFile.getParent() != null) &&
(psiFile.getParent().getName().equals("custom-sql"))
) {
if (context instanceof XmlTag) {
XmlTag xmlTag = (XmlTag) context;
String tagName = xmlTag.getName();
if ("sql".equals(tagName)) {
InjectedLanguage sqlLanguage = InjectedLanguage.create(SqlLanguage.INSTANCE.getID(), "", "", true);
List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> list = new ArrayList<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>>();
PsiElement[] myChildren = xmlTag.getChildren();
for (PsiElement child : myChildren) {
if (child instanceof XmlText) {
if (((PsiLanguageInjectionHost)child).isValidHost()) {
TextRange textRange = ElementManipulators.getManipulator(child).getRangeInElement(child);
String text = child.getText();
if (text != null) {
int cdataStart = text.indexOf(CDATA_START);
int cdataEnd = text.indexOf(CDATA_END);
if (cdataStart > -1 && cdataEnd > -1 && cdataEnd > cdataStart) {
textRange = new TextRange(cdataStart + CDATA_START.length(), cdataEnd);
}
list.add(
Trinity.create(
((PsiLanguageInjectionHost) child),
sqlLanguage,
textRange
)
);
}
}
}
}
if (!list.isEmpty()) {
InjectorUtils.registerInjection(
SqlLanguage.INSTANCE,
list,
xmlTag.getContainingFile(),
registrar
);
}
}
}
}
}
@NotNull
public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
return List.of(XmlTag.class);
}
}
Please sign in to leave a comment.
Hi Dominik,
Could you please check if the issue is the same as here (please check the attached recording)?
https://youtrack.jetbrains.com/issue/IDEA-238976
Yes, it seems that it may be the same issue. So I have to wait until it's fixed :-)
Hi Dominik,
I suggest adding your information to the ticket, so it is better visible it affects more users.