diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 3e06b23fe..04f9d69c7 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -564,6 +564,8 @@ + + diff --git a/src/com/magento/idea/magento2plugin/lang/injection/UiComponentSyntaxInjector.java b/src/com/magento/idea/magento2plugin/lang/injection/UiComponentSyntaxInjector.java new file mode 100644 index 000000000..e202d6539 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/lang/injection/UiComponentSyntaxInjector.java @@ -0,0 +1,82 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2plugin.lang.injection; + +import com.intellij.json.JsonLanguage; +import com.intellij.lang.injection.MultiHostInjector; +import com.intellij.lang.injection.MultiHostRegistrar; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiLanguageInjectionHost; +import com.intellij.psi.html.HtmlTag; +import com.intellij.psi.templateLanguages.OuterLanguageElement; +import com.intellij.psi.xml.XmlText; +import java.util.List; +import org.jetbrains.annotations.NotNull; + +public class UiComponentSyntaxInjector implements MultiHostInjector { + + @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops") + @Override + public void getLanguagesToInject( + final @NotNull MultiHostRegistrar registrar, + final @NotNull PsiElement host + ) { + if (!isUiComponentTag(host)) { + return; + } + PsiElement targetXmlText = null; + + for (final PsiElement element : host.getChildren()) { + if (element instanceof XmlText) { + targetXmlText = element; + break; + } + } + + if (targetXmlText == null) { + return; + } + registrar.startInjecting(JsonLanguage.INSTANCE); + int startPosition = 0; + + for (final PsiElement element : targetXmlText.getChildren()) { + if (!(element instanceof OuterLanguageElement)) { + final int endPosition = Math.min( + startPosition + element.getTextLength(), + targetXmlText.getTextLength() + ); + + if (startPosition > element.getStartOffsetInParent()) { + startPosition = element.getStartOffsetInParent(); + } + registrar.addPlace( + null, + null, + (PsiLanguageInjectionHost) targetXmlText, + new TextRange(startPosition, endPosition) + ); + } + startPosition += element.getTextLength(); + } + registrar.doneInjecting(); + } + + @Override + public @NotNull List> elementsToInjectIn() { + return List.of(HtmlTag.class); + } + + private boolean isUiComponentTag(final @NotNull PsiElement host) { + if (!(host instanceof HtmlTag)) { + return false; + } + final HtmlTag tag = (HtmlTag) host; + final String typeAttributeValue = tag.getAttributeValue("type"); + + return typeAttributeValue != null && typeAttributeValue.equals("text/x-magento-init"); + } +}