CDATA inside MultiHostInjector

Answered

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);
    }

}

 

3 comments
Comment actions Permalink

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

0
Comment actions Permalink

Yes, it seems that it may be the same issue. So I have to wait until it's fixed :-)

0
Comment actions Permalink

Hi Dominik,

I suggest adding your information to the ticket, so it is better visible it affects more users.

0

Please sign in to leave a comment.