Search in sources :

Example 1 with OuterLanguageElement

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

the class HtmlLocalInspectionTool method buildVisitor.

@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
    return new XmlElementVisitor() {

        @Override
        public void visitXmlToken(final XmlToken token) {
            IElementType tokenType = token.getTokenType();
            if (tokenType == XmlTokenType.XML_NAME || tokenType == XmlTokenType.XML_TAG_NAME) {
                PsiElement element = token.getPrevSibling();
                while (element instanceof PsiWhiteSpace) element = element.getPrevSibling();
                if (element instanceof XmlToken && ((XmlToken) element).getTokenType() == XmlTokenType.XML_START_TAG_START) {
                    PsiElement parent = element.getParent();
                    if (parent instanceof XmlTag && !(token.getNextSibling() instanceof OuterLanguageElement)) {
                        XmlTag tag = (XmlTag) parent;
                        checkTag(tag, holder, isOnTheFly);
                    }
                }
            }
        }

        @Override
        public void visitXmlAttribute(final XmlAttribute attribute) {
            checkAttribute(attribute, holder, isOnTheFly);
        }
    };
}
Also used : XmlElementVisitor(com.intellij.psi.XmlElementVisitor) IElementType(com.intellij.psi.tree.IElementType) OuterLanguageElement(com.intellij.psi.templateLanguages.OuterLanguageElement) XmlAttribute(com.intellij.psi.xml.XmlAttribute) PsiElement(com.intellij.psi.PsiElement) XmlToken(com.intellij.psi.xml.XmlToken) PsiWhiteSpace(com.intellij.psi.PsiWhiteSpace) XmlTag(com.intellij.psi.xml.XmlTag) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with OuterLanguageElement

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

the class XmlGtTypedHandler method beforeCharTyped.

@Override
public Result beforeCharTyped(final char c, final Project project, Editor editor, PsiFile editedFile, final FileType fileType) {
    final WebEditorOptions webEditorOptions = WebEditorOptions.getInstance();
    if (c == '>' && webEditorOptions != null && webEditorOptions.isAutomaticallyInsertClosingTag() && fileContainsXmlLanguage(editedFile)) {
        PsiDocumentManager.getInstance(project).commitAllDocuments();
        PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
        FileViewProvider provider = editedFile.getViewProvider();
        int offset = editor.getCaretModel().getOffset();
        PsiElement element, elementAtCaret = null;
        if (offset < editor.getDocument().getTextLength()) {
            elementAtCaret = element = provider.findElementAt(offset, XMLLanguage.class);
            if (element == null && offset > 0) {
                // seems like a template language
                // <xml_code><caret><outer_element>
                elementAtCaret = element = provider.findElementAt(offset - 1, XMLLanguage.class);
            }
            if (!(element instanceof PsiWhiteSpace)) {
                boolean nonAcceptableDelimiter = true;
                if (element instanceof XmlToken) {
                    IElementType tokenType = ((XmlToken) element).getTokenType();
                    if (tokenType == XmlTokenType.XML_START_TAG_START || tokenType == XmlTokenType.XML_END_TAG_START) {
                        if (offset > 0) {
                            PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);
                            if (previousElement instanceof XmlToken) {
                                tokenType = ((XmlToken) previousElement).getTokenType();
                                element = previousElement;
                                nonAcceptableDelimiter = false;
                            }
                        }
                    } else if (tokenType == XmlTokenType.XML_NAME || tokenType == XmlTokenType.XML_TAG_NAME) {
                        if (element.getNextSibling() instanceof PsiErrorElement) {
                            nonAcceptableDelimiter = false;
                        }
                    }
                    if (tokenType == XmlTokenType.XML_TAG_END || tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END && element.getTextOffset() == offset - 1) {
                        EditorModificationUtil.moveCaretRelatively(editor, 1);
                        editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
                        return Result.STOP;
                    }
                }
                if (nonAcceptableDelimiter)
                    return Result.CONTINUE;
            } else {
                // check if right after empty end
                PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);
                if (previousElement instanceof XmlToken) {
                    final IElementType tokenType = ((XmlToken) previousElement).getTokenType();
                    if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END) {
                        return Result.STOP;
                    }
                }
            }
            PsiElement parent = element.getParent();
            if (parent instanceof XmlText) {
                final String text = parent.getText();
                // check /
                final int index = offset - parent.getTextOffset() - 1;
                if (index >= 0 && text.charAt(index) == '/') {
                    // already seen /
                    return Result.CONTINUE;
                }
                element = parent.getPrevSibling();
            } else if (parent instanceof XmlTag && !(element.getPrevSibling() instanceof XmlTag) && !(element.getPrevSibling() instanceof OuterLanguageElement)) {
                element = parent;
            } else if (parent instanceof XmlAttributeValue) {
                element = parent;
            }
        } else {
            element = provider.findElementAt(editor.getDocument().getTextLength() - 1, XMLLanguage.class);
            if (element == null)
                return Result.CONTINUE;
            element = element.getParent();
        }
        if (offset > 0 && offset <= editor.getDocument().getTextLength()) {
            if (editor.getDocument().getCharsSequence().charAt(offset - 1) == '/') {
                // Some languages (e.g. GSP) allow character '/' in tag name.
                return Result.CONTINUE;
            }
        }
        if (element instanceof XmlAttributeValue) {
            element = element.getParent().getParent();
        }
        while (element instanceof PsiWhiteSpace || element instanceof OuterLanguageElement) element = element.getPrevSibling();
        if (element instanceof XmlDocument) {
            // hack for closing tags in RHTML
            element = element.getLastChild();
        }
        if (element == null)
            return Result.CONTINUE;
        if (!(element instanceof XmlTag)) {
            if (element instanceof XmlTokenImpl && element.getPrevSibling() != null && element.getPrevSibling().getText().equals("<")) {
                // tag is started and there is another text in the end
                EditorModificationUtil.insertStringAtCaret(editor, "</" + element.getText() + ">", false, 0);
            }
            return Result.CONTINUE;
        }
        XmlTag tag = (XmlTag) element;
        if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) != null)
            return Result.CONTINUE;
        if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null)
            return Result.CONTINUE;
        final XmlToken startToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_START_TAG_START);
        if (startToken == null || !startToken.getText().equals("<"))
            return Result.CONTINUE;
        String name = tag.getName();
        if (elementAtCaret instanceof XmlToken && (((XmlToken) elementAtCaret).getTokenType() == XmlTokenType.XML_NAME || ((XmlToken) elementAtCaret).getTokenType() == XmlTokenType.XML_TAG_NAME)) {
            name = name.substring(0, offset - elementAtCaret.getTextOffset());
        }
        if (tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(name))
            return Result.CONTINUE;
        if (name.isEmpty())
            return Result.CONTINUE;
        int tagOffset = tag.getTextRange().getStartOffset();
        final XmlToken nameToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_NAME);
        if (nameToken != null && nameToken.getTextRange().getStartOffset() > offset)
            return Result.CONTINUE;
        HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(tagOffset);
        if (BraceMatchingUtil.matchBrace(editor.getDocument().getCharsSequence(), editedFile.getFileType(), iterator, true, true)) {
            PsiElement parent = tag.getParent();
            boolean hasBalance = true;
            loop: while (parent instanceof XmlTag) {
                if (name.equals(((XmlTag) parent).getName())) {
                    hasBalance = false;
                    ASTNode astNode = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode());
                    if (astNode == null) {
                        hasBalance = true;
                        break;
                    }
                    for (PsiElement el = parent.getNextSibling(); el != null; el = el.getNextSibling()) {
                        if (el instanceof PsiErrorElement && el.getText().startsWith("</" + name)) {
                            hasBalance = true;
                            break loop;
                        }
                    }
                }
                parent = parent.getParent();
            }
            if (hasBalance)
                return Result.CONTINUE;
        }
        Collection<TextRange> cdataReformatRanges = null;
        final XmlElementDescriptor descriptor = tag.getDescriptor();
        EditorModificationUtil.insertStringAtCaret(editor, "</" + name + ">", false, 0);
        if (descriptor instanceof XmlElementDescriptorWithCDataContent) {
            final XmlElementDescriptorWithCDataContent cDataContainer = (XmlElementDescriptorWithCDataContent) descriptor;
            cdataReformatRanges = ContainerUtil.newSmartList();
            if (cDataContainer.requiresCdataBracesInContext(tag)) {
                @NonNls final String cDataStart = "><![CDATA[";
                final String inserted = cDataStart + "\n]]>";
                EditorModificationUtil.insertStringAtCaret(editor, inserted, false, cDataStart.length());
                int caretOffset = editor.getCaretModel().getOffset();
                if (caretOffset >= cDataStart.length()) {
                    cdataReformatRanges.add(TextRange.from(caretOffset - cDataStart.length(), inserted.length() + 1));
                }
            }
        }
        if (cdataReformatRanges != null && !cdataReformatRanges.isEmpty()) {
            PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
            try {
                CodeStyleManager.getInstance(project).reformatText(file, cdataReformatRanges);
            } catch (IncorrectOperationException e) {
                LOG.error(e);
            }
        }
        return cdataReformatRanges != null && !cdataReformatRanges.isEmpty() ? Result.STOP : Result.CONTINUE;
    }
    return Result.CONTINUE;
}
Also used : OuterLanguageElement(com.intellij.psi.templateLanguages.OuterLanguageElement) XmlTokenImpl(com.intellij.psi.impl.source.xml.XmlTokenImpl) TemplateLanguageFileViewProvider(com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider) WebEditorOptions(com.intellij.application.options.editor.WebEditorOptions) ASTNode(com.intellij.lang.ASTNode) XMLLanguage(com.intellij.lang.xml.XMLLanguage) NonNls(org.jetbrains.annotations.NonNls) HtmlTag(com.intellij.psi.html.HtmlTag) TextRange(com.intellij.openapi.util.TextRange) IElementType(com.intellij.psi.tree.IElementType) XmlElementDescriptorWithCDataContent(com.intellij.xml.XmlElementDescriptorWithCDataContent) IncorrectOperationException(com.intellij.util.IncorrectOperationException) XmlElementDescriptor(com.intellij.xml.XmlElementDescriptor) HighlighterIterator(com.intellij.openapi.editor.highlighter.HighlighterIterator)

Example 3 with OuterLanguageElement

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

the class XmlSlashTypedHandler method charTyped.

@Override
public Result charTyped(final char c, final Project project, @NotNull final Editor editor, @NotNull final PsiFile editedFile) {
    if (!WebEditorOptions.getInstance().isAutoCloseTag())
        return Result.CONTINUE;
    if (c == '/' && XmlGtTypedHandler.fileContainsXmlLanguage(editedFile)) {
        PsiDocumentManager.getInstance(project).commitAllDocuments();
        PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
        if (file == null)
            return Result.CONTINUE;
        FileViewProvider provider = file.getViewProvider();
        final int offset = editor.getCaretModel().getOffset();
        PsiElement element = provider.findElementAt(offset - 1, XMLLanguage.class);
        if (element == null)
            return Result.CONTINUE;
        if (!(element.getLanguage() instanceof XMLLanguage))
            return Result.CONTINUE;
        ASTNode prevLeaf = element.getNode();
        if (prevLeaf == null)
            return Result.CONTINUE;
        final String prevLeafText = prevLeaf.getText();
        if ("</".equals(prevLeafText) && prevLeaf.getElementType() == XmlTokenType.XML_END_TAG_START) {
            XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
            if (tag != null && StringUtil.isNotEmpty(tag.getName()) && TreeUtil.findSibling(prevLeaf, XmlTokenType.XML_NAME) == null) {
                // check for template language like JSP
                if (provider instanceof MultiplePsiFilesPerDocumentFileViewProvider) {
                    PsiElement element1 = SingleRootFileViewProvider.findElementAt(file, offset - 1);
                    if (element1 != null) {
                        // case of top-level jsp tag
                        XmlTag tag1 = PsiTreeUtil.getParentOfType(element1, XmlTag.class);
                        if (shouldReplace(tag, tag1, offset)) {
                            tag = tag1;
                        } else {
                            // if we have enclosing jsp tag, actual tag to be completed will be previous sibling
                            tag1 = PsiTreeUtil.getPrevSiblingOfType(element1.getParent(), XmlTag.class);
                            if (shouldReplace(tag, tag1, offset)) {
                                tag = tag1;
                            }
                        }
                    }
                }
                EditorModificationUtil.insertStringAtCaret(editor, tag.getName() + ">", false);
                autoIndent(editor);
                return Result.STOP;
            }
        }
        if (!"/".equals(prevLeafText.trim()))
            return Result.CONTINUE;
        while ((prevLeaf = TreeUtil.prevLeaf(prevLeaf)) != null && prevLeaf.getElementType() == XmlTokenType.XML_WHITE_SPACE) ;
        if (prevLeaf instanceof OuterLanguageElement) {
            element = file.getViewProvider().findElementAt(offset - 1, file.getLanguage());
            prevLeaf = element != null ? element.getNode() : null;
            while ((prevLeaf = TreeUtil.prevLeaf(prevLeaf)) != null && prevLeaf.getElementType() == XmlTokenType.XML_WHITE_SPACE) ;
        }
        if (prevLeaf == null)
            return Result.CONTINUE;
        XmlTag tag = PsiTreeUtil.getParentOfType(prevLeaf.getPsi(), XmlTag.class);
        if (tag == null) {
            // prevLeaf maybe in one tree and element in another
            PsiElement element2 = provider.findElementAt(prevLeaf.getStartOffset(), XMLLanguage.class);
            tag = PsiTreeUtil.getParentOfType(element2, XmlTag.class);
            if (tag == null)
                return Result.CONTINUE;
        }
        final XmlToken startToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_START_TAG_START);
        if (startToken == null || !startToken.getText().equals("<"))
            return Result.CONTINUE;
        if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) != null)
            return Result.CONTINUE;
        if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null)
            return Result.CONTINUE;
        if (PsiTreeUtil.getParentOfType(element, XmlAttributeValue.class) != null)
            return Result.CONTINUE;
        EditorModificationUtil.insertStringAtCaret(editor, ">", false);
        return Result.STOP;
    }
    return Result.CONTINUE;
}
Also used : OuterLanguageElement(com.intellij.psi.templateLanguages.OuterLanguageElement) ASTNode(com.intellij.lang.ASTNode) XMLLanguage(com.intellij.lang.xml.XMLLanguage)

Example 4 with OuterLanguageElement

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

the class PyBaseElementImpl method findReferenceAt.

/**
   * Overrides the findReferenceAt() logic in order to provide a resolve context with origin file for returned references.
   * The findReferenceAt() is usually invoked from UI operations, and it helps to be able to do deeper analysis in the
   * current file for such operations.
   *
   * @param offset the offset to find the reference at
   * @return the reference or null.
   */
@Override
public PsiReference findReferenceAt(int offset) {
    // copy/paste from SharedPsiElementImplUtil
    PsiElement element = findElementAt(offset);
    if (element == null || element instanceof OuterLanguageElement)
        return null;
    offset = getTextRange().getStartOffset() + offset - element.getTextRange().getStartOffset();
    List<PsiReference> referencesList = new ArrayList<>();
    final PsiFile file = element.getContainingFile();
    final PyResolveContext resolveContext = file != null ? PyResolveContext.defaultContext().withTypeEvalContext(TypeEvalContext.codeAnalysis(file.getProject(), file)) : PyResolveContext.defaultContext();
    while (element != null) {
        addReferences(offset, element, referencesList, resolveContext);
        offset = element.getStartOffsetInParent() + offset;
        if (element instanceof PsiFile)
            break;
        element = element.getParent();
    }
    if (referencesList.isEmpty())
        return null;
    if (referencesList.size() == 1)
        return referencesList.get(0);
    return new PsiMultiReference(referencesList.toArray(new PsiReference[referencesList.size()]), referencesList.get(referencesList.size() - 1).getElement());
}
Also used : OuterLanguageElement(com.intellij.psi.templateLanguages.OuterLanguageElement) PyResolveContext(com.jetbrains.python.psi.resolve.PyResolveContext) ArrayList(java.util.ArrayList) PsiMultiReference(com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference)

Example 5 with OuterLanguageElement

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

the class XmlBlock method splitComment.

protected List<Block> splitComment() {
    if (myNode.getElementType() != XmlElementType.XML_COMMENT)
        return EMPTY;
    final ArrayList<Block> result = new ArrayList<>(3);
    ASTNode child = myNode.getFirstChildNode();
    boolean hasOuterLangElements = false;
    while (child != null) {
        if (child instanceof OuterLanguageElement) {
            hasOuterLangElements = true;
        }
        result.add(new XmlBlock(child, null, null, myXmlFormattingPolicy, getChildIndent(), null, isPreserveSpace()));
        child = child.getTreeNext();
    }
    if (hasOuterLangElements) {
        return result;
    } else {
        return EMPTY;
    }
}
Also used : OuterLanguageElement(com.intellij.psi.templateLanguages.OuterLanguageElement) ArrayList(java.util.ArrayList) ASTNode(com.intellij.lang.ASTNode) AbstractBlock(com.intellij.psi.formatter.common.AbstractBlock)

Aggregations

OuterLanguageElement (com.intellij.psi.templateLanguages.OuterLanguageElement)15 PsiElement (com.intellij.psi.PsiElement)6 ASTNode (com.intellij.lang.ASTNode)5 TextRange (com.intellij.openapi.util.TextRange)4 IElementType (com.intellij.psi.tree.IElementType)4 ArrayList (java.util.ArrayList)4 PsiFile (com.intellij.psi.PsiFile)3 PsiWhiteSpace (com.intellij.psi.PsiWhiteSpace)3 NotNull (org.jetbrains.annotations.NotNull)3 Nullable (org.jetbrains.annotations.Nullable)3 Language (com.intellij.lang.Language)2 XMLLanguage (com.intellij.lang.xml.XMLLanguage)2 XmlAttribute (com.intellij.psi.xml.XmlAttribute)2 XmlTag (com.intellij.psi.xml.XmlTag)2 IncorrectOperationException (com.intellij.util.IncorrectOperationException)2 XmlElementDescriptor (com.intellij.xml.XmlElementDescriptor)2 WebEditorOptions (com.intellij.application.options.editor.WebEditorOptions)1 HighlightInfo (com.intellij.codeInsight.daemon.impl.HighlightInfo)1 Document (com.intellij.openapi.editor.Document)1 HighlighterIterator (com.intellij.openapi.editor.highlighter.HighlighterIterator)1