Search in sources :

Example 21 with PsiLanguageInjectionHost

use of com.intellij.psi.PsiLanguageInjectionHost in project intellij-community by JetBrains.

the class XmlLanguageInjector method getInjectedLanguage.

void getInjectedLanguage(final PsiElement place, final Ref<Boolean> unparsableRef, final PairProcessor<Language, List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>>> processor) {
    if (place instanceof XmlTag) {
        final XmlTag xmlTag = (XmlTag) place;
        List<BaseInjection> injections = myConfiguration.getInjections(XmlLanguageInjectionSupport.XML_SUPPORT_ID);
        //noinspection ForLoopReplaceableByForEach
        for (int i = 0, injectionsSize = injections.size(); i < injectionsSize; i++) {
            final BaseInjection injection = injections.get(i);
            if (injection.acceptsPsiElement(xmlTag)) {
                final Language language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId());
                if (language == null)
                    continue;
                final boolean separateFiles = !injection.isSingleFile() && StringUtil.isNotEmpty(injection.getValuePattern());
                final List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> result = ContainerUtil.newArrayList();
                xmlTag.acceptChildren(new PsiElementVisitor() {

                    @Override
                    public void visitElement(final PsiElement element) {
                        if (element instanceof XmlText) {
                            if (!(element instanceof PsiLanguageInjectionHost) || element.getTextLength() == 0)
                                return;
                            final List<TextRange> list = injection.getInjectedArea(element);
                            final InjectedLanguage l = InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false);
                            for (TextRange textRange : list) {
                                result.add(Trinity.create((PsiLanguageInjectionHost) element, l, textRange));
                            }
                        } else if (element instanceof XmlTag) {
                            if (!separateFiles)
                                unparsableRef.set(Boolean.TRUE);
                            if (injection instanceof AbstractTagInjection && ((AbstractTagInjection) injection).isApplyToSubTags()) {
                                element.acceptChildren(this);
                            }
                        }
                    }
                });
                if (!result.isEmpty()) {
                    if (separateFiles) {
                        for (Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange> trinity : result) {
                            processor.process(language, Collections.singletonList(trinity));
                        }
                    } else {
                        processor.process(language, result);
                    }
                }
                if (injection.isTerminal()) {
                    break;
                }
            }
        }
    } else if (place instanceof XmlAttributeValue && place.getParent() instanceof XmlAttribute) {
        final XmlAttribute attribute = (XmlAttribute) place.getParent();
        final XmlAttributeValue value = (XmlAttributeValue) place;
        //if (value == null) return;
        // Check that we don't inject anything into embedded (e.g. JavaScript) content:
        // XmlToken: "
        // JSEmbeddedContent
        // XmlToken "
        // Actually IDEA shouldn't ask for injected languages at all in this case.
        final PsiElement[] children = value.getChildren();
        if (children.length < 3 || !(children[1] instanceof XmlToken) || ((XmlToken) children[1]).getTokenType() != XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) {
            return;
        }
        List<BaseInjection> injections = myConfiguration.getInjections(XmlLanguageInjectionSupport.XML_SUPPORT_ID);
        //noinspection ForLoopReplaceableByForEach
        for (int i = 0, size = injections.size(); i < size; i++) {
            BaseInjection injection = injections.get(i);
            if (injection.acceptsPsiElement(attribute)) {
                final Language language = InjectedLanguage.findLanguageById(injection.getInjectedLanguageId());
                if (language == null)
                    continue;
                final boolean separateFiles = !injection.isSingleFile() && StringUtil.isNotEmpty(injection.getValuePattern());
                final List<TextRange> ranges = injection.getInjectedArea(value);
                if (ranges.isEmpty())
                    continue;
                final List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> result = new ArrayList<>();
                final InjectedLanguage l = InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false);
                for (TextRange textRange : ranges) {
                    result.add(Trinity.create((PsiLanguageInjectionHost) value, l, textRange));
                }
                if (separateFiles) {
                    for (Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange> trinity : result) {
                        processor.process(language, Collections.singletonList(trinity));
                    }
                } else {
                    processor.process(language, result);
                }
                if (injection.isTerminal()) {
                    break;
                }
            }
        }
    }
}
Also used : Trinity(com.intellij.openapi.util.Trinity) TextRange(com.intellij.openapi.util.TextRange) PsiElementVisitor(com.intellij.psi.PsiElementVisitor) BaseInjection(org.intellij.plugins.intelliLang.inject.config.BaseInjection) Language(com.intellij.lang.Language) InjectedLanguage(org.intellij.plugins.intelliLang.inject.InjectedLanguage) InjectedLanguage(org.intellij.plugins.intelliLang.inject.InjectedLanguage) PsiLanguageInjectionHost(com.intellij.psi.PsiLanguageInjectionHost) AbstractTagInjection(org.intellij.plugins.intelliLang.inject.config.AbstractTagInjection) PsiElement(com.intellij.psi.PsiElement)

Example 22 with PsiLanguageInjectionHost

use of com.intellij.psi.PsiLanguageInjectionHost in project intellij-community by JetBrains.

the class InjectedLanguageBlockBuilder method addInjectedBlocks.

public boolean addInjectedBlocks(List<Block> result, final ASTNode injectionHost, Wrap wrap, Alignment alignment, Indent indent) {
    final PsiFile[] injectedFile = new PsiFile[1];
    final Ref<TextRange> injectedRangeInsideHost = new Ref<>();
    final Ref<Integer> prefixLength = new Ref<>();
    final Ref<Integer> suffixLength = new Ref<>();
    final Ref<ASTNode> injectionHostToUse = new Ref<>(injectionHost);
    final PsiLanguageInjectionHost.InjectedPsiVisitor injectedPsiVisitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {

        @Override
        public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List<PsiLanguageInjectionHost.Shred> places) {
            if (places.size() != 1) {
                return;
            }
            final PsiLanguageInjectionHost.Shred shred = places.get(0);
            TextRange textRange = shred.getRangeInsideHost();
            PsiLanguageInjectionHost shredHost = shred.getHost();
            if (shredHost == null) {
                return;
            }
            ASTNode node = shredHost.getNode();
            if (node == null) {
                return;
            }
            if (node != injectionHost) {
                int shift = 0;
                boolean canProcess = false;
                for (ASTNode n = injectionHost.getTreeParent(), prev = injectionHost; n != null; prev = n, n = n.getTreeParent()) {
                    shift += n.getStartOffset() - prev.getStartOffset();
                    if (n == node) {
                        textRange = textRange.shiftRight(shift);
                        canProcess = true;
                        break;
                    }
                }
                if (!canProcess) {
                    return;
                }
            }
            String childText;
            if ((injectionHost.getTextLength() == textRange.getEndOffset() && textRange.getStartOffset() == 0) || (canProcessFragment((childText = injectionHost.getText()).substring(0, textRange.getStartOffset()), injectionHost) && canProcessFragment(childText.substring(textRange.getEndOffset()), injectionHost))) {
                injectedFile[0] = injectedPsi;
                injectedRangeInsideHost.set(textRange);
                prefixLength.set(shred.getPrefix().length());
                suffixLength.set(shred.getSuffix().length());
            }
        }
    };
    final PsiElement injectionHostPsi = injectionHost.getPsi();
    InjectedLanguageUtil.enumerate(injectionHostPsi, injectionHostPsi.getContainingFile(), false, injectedPsiVisitor);
    if (injectedFile[0] != null) {
        final Language childLanguage = injectedFile[0].getLanguage();
        final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(childLanguage, injectionHostPsi);
        if (builder != null) {
            final int startOffset = injectedRangeInsideHost.get().getStartOffset();
            final int endOffset = injectedRangeInsideHost.get().getEndOffset();
            TextRange range = injectionHostToUse.get().getTextRange();
            int childOffset = range.getStartOffset();
            if (startOffset != 0) {
                final ASTNode leaf = injectionHostToUse.get().findLeafElementAt(startOffset - 1);
                result.add(createBlockBeforeInjection(leaf, wrap, alignment, indent, new TextRange(childOffset, childOffset + startOffset)));
            }
            addInjectedLanguageBlockWrapper(result, injectedFile[0].getNode(), indent, childOffset + startOffset, new TextRange(prefixLength.get(), injectedFile[0].getTextLength() - suffixLength.get()));
            if (endOffset != injectionHostToUse.get().getTextLength()) {
                final ASTNode leaf = injectionHostToUse.get().findLeafElementAt(endOffset);
                result.add(createBlockAfterInjection(leaf, wrap, alignment, indent, new TextRange(childOffset + endOffset, range.getEndOffset())));
            }
            return true;
        }
    }
    return false;
}
Also used : TextRange(com.intellij.openapi.util.TextRange) NotNull(org.jetbrains.annotations.NotNull) Ref(com.intellij.openapi.util.Ref) Language(com.intellij.lang.Language) PsiLanguageInjectionHost(com.intellij.psi.PsiLanguageInjectionHost) ASTNode(com.intellij.lang.ASTNode) PsiFile(com.intellij.psi.PsiFile) List(java.util.List) PsiElement(com.intellij.psi.PsiElement)

Example 23 with PsiLanguageInjectionHost

use of com.intellij.psi.PsiLanguageInjectionHost in project intellij-community by JetBrains.

the class IElementTypeTest method testManipulatorRegistered.

public void testManipulatorRegistered() {
    LanguageExtensionPoint[] extensions = Extensions.getExtensions(new ExtensionPointName<LanguageExtensionPoint>("com.intellij.lang.parserDefinition"));
    Set<String> classes = new HashSet<>();
    List<String> failures = new ArrayList<>();
    int total = 0;
    for (LanguageExtensionPoint e : extensions) {
        ParserDefinition definition = (ParserDefinition) e.getInstance();
        for (IElementType type : IElementType.enumerate(IElementType.TRUE)) {
            if (type instanceof ILeafElementType)
                continue;
            try {
                CompositeElement treeElement = ASTFactory.composite(type);
                total++;
                PsiElement element = treeElement instanceof PsiElement ? (PsiElement) treeElement : definition.createElement(treeElement);
                if (element instanceof PsiLanguageInjectionHost && classes.add(element.getClass().getName())) {
                    boolean ok = ElementManipulators.getManipulator(element) != null;
                    System.out.println((ok ? "OK  " : "FAIL") + " " + element.getClass().getSimpleName() + " [" + definition.getClass().getSimpleName() + "]");
                    if (!ok)
                        failures.add(element.getClass().getName());
                }
            } catch (Throwable ignored) {
            }
        }
    }
    System.out.println("count: " + classes.size() + ", total: " + total);
    assertEmpty("PsiLanguageInjectionHost requires " + ElementManipulators.EP_NAME, failures);
}
Also used : ArrayList(java.util.ArrayList) PsiLanguageInjectionHost(com.intellij.psi.PsiLanguageInjectionHost) CompositeElement(com.intellij.psi.impl.source.tree.CompositeElement) PsiElement(com.intellij.psi.PsiElement) HashSet(com.intellij.util.containers.HashSet)

Example 24 with PsiLanguageInjectionHost

use of com.intellij.psi.PsiLanguageInjectionHost in project intellij-community by JetBrains.

the class XsltCodeInsightUtil method getRangeInsideHostingFile.

@NotNull
public static TextRange getRangeInsideHostingFile(XPathElement expr) {
    final PsiLanguageInjectionHost host = PsiTreeUtil.getContextOfType(expr, PsiLanguageInjectionHost.class, true);
    assert host != null;
    final List<Pair<PsiElement, TextRange>> psi = InjectedLanguageManager.getInstance(host.getProject()).getInjectedPsiFiles(host);
    assert psi != null;
    for (Pair<PsiElement, TextRange> pair : psi) {
        if (PsiTreeUtil.isAncestor(pair.first, expr, false)) {
            return expr.getTextRange().shiftRight(pair.second.getStartOffset() + host.getTextRange().getStartOffset());
        }
    }
    assert false;
    return null;
}
Also used : PsiLanguageInjectionHost(com.intellij.psi.PsiLanguageInjectionHost) TextRange(com.intellij.openapi.util.TextRange) PsiElement(com.intellij.psi.PsiElement) Pair(com.intellij.openapi.util.Pair) NotNull(org.jetbrains.annotations.NotNull)

Example 25 with PsiLanguageInjectionHost

use of com.intellij.psi.PsiLanguageInjectionHost in project intellij-community by JetBrains.

the class PyDocstringFile method getLanguageLevel.

@Override
public LanguageLevel getLanguageLevel() {
    final InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(getProject());
    final PsiLanguageInjectionHost host = languageManager.getInjectionHost(this);
    if (host != null)
        return LanguageLevel.forElement(host.getContainingFile());
    return super.getLanguageLevel();
}
Also used : InjectedLanguageManager(com.intellij.lang.injection.InjectedLanguageManager) PsiLanguageInjectionHost(com.intellij.psi.PsiLanguageInjectionHost)

Aggregations

PsiLanguageInjectionHost (com.intellij.psi.PsiLanguageInjectionHost)41 PsiElement (com.intellij.psi.PsiElement)23 TextRange (com.intellij.openapi.util.TextRange)19 InjectedLanguageManager (com.intellij.lang.injection.InjectedLanguageManager)10 NotNull (org.jetbrains.annotations.NotNull)10 PsiFile (com.intellij.psi.PsiFile)9 Pair (com.intellij.openapi.util.Pair)8 Language (com.intellij.lang.Language)6 XmlAttribute (com.intellij.psi.xml.XmlAttribute)5 List (java.util.List)4 Nullable (org.jetbrains.annotations.Nullable)4 ASTNode (com.intellij.lang.ASTNode)3 XmlAttributeValueImpl (com.intellij.psi.impl.source.xml.XmlAttributeValueImpl)3 ScopeOwner (com.jetbrains.python.codeInsight.controlflow.ScopeOwner)3 InjectedLanguage (org.intellij.plugins.intelliLang.inject.InjectedLanguage)3 NonNls (org.jetbrains.annotations.NonNls)3 Project (com.intellij.openapi.project.Project)2 HtmlTag (com.intellij.psi.html.HtmlTag)2 TemplateBuilder (com.intellij.codeInsight.template.TemplateBuilder)1 AnnotationBackedDescriptor (com.intellij.lang.javascript.flex.AnnotationBackedDescriptor)1