Search in sources :

Example 1 with CharTable

use of com.intellij.util.CharTable in project intellij-community by JetBrains.

the class XmlWhiteSpaceFormattingStrategy method addWhitespaceToTagBody.

private static void addWhitespaceToTagBody(final ASTNode treePrev, final LeafElement whiteSpaceElement) {
    final CharTable charTable = SharedImplUtil.findCharTableByTree(treePrev);
    final ASTNode treeParent = treePrev.getTreeParent();
    final boolean before;
    final XmlText xmlText;
    if (treePrev.getElementType() == XmlElementType.XML_TEXT) {
        xmlText = (XmlText) treePrev.getPsi();
        before = true;
    } else if (treePrev.getTreePrev().getElementType() == XmlElementType.XML_TEXT) {
        xmlText = (XmlText) treePrev.getTreePrev().getPsi();
        before = false;
    } else {
        xmlText = (XmlText) Factory.createCompositeElement(XmlElementType.XML_TEXT, charTable, treeParent.getPsi().getManager());
        CodeEditUtil.setNodeGenerated(xmlText.getNode(), true);
        treeParent.addChild(xmlText.getNode(), treePrev);
        before = true;
    }
    final ASTNode node = xmlText.getNode();
    assert node != null;
    final TreeElement anchorInText = (TreeElement) (before ? node.getFirstChildNode() : node.getLastChildNode());
    if (anchorInText == null)
        node.addChild(whiteSpaceElement);
    else if (anchorInText.getElementType() != XmlTokenType.XML_WHITE_SPACE)
        node.addChild(whiteSpaceElement, before ? anchorInText : null);
    else {
        final String text = before ? whiteSpaceElement.getText() + anchorInText.getText() : anchorInText.getText() + whiteSpaceElement.getText();
        node.replaceChild(anchorInText, ASTFactory.whitespace(text));
    }
}
Also used : ASTNode(com.intellij.lang.ASTNode) XmlText(com.intellij.psi.xml.XmlText) CharTable(com.intellij.util.CharTable) TreeElement(com.intellij.psi.impl.source.tree.TreeElement)

Example 2 with CharTable

use of com.intellij.util.CharTable in project intellij-community by JetBrains.

the class XmlAspectImpl method update.

@Override
public void update(PomModelEvent event) {
    if (!event.getChangedAspects().contains(myTreeAspect))
        return;
    final TreeChangeEvent changeSet = (TreeChangeEvent) event.getChangeSet(myTreeAspect);
    if (changeSet == null)
        return;
    final ASTNode rootElement = changeSet.getRootElement();
    final PsiFile file = (PsiFile) rootElement.getPsi();
    if (!(file instanceof XmlFile))
        return;
    final XmlAspectChangeSetImpl xmlChangeSet = event.registerChangeSetIfAbsent(this, new XmlAspectChangeSetImpl(myModel));
    xmlChangeSet.addChangedFile((XmlFile) file);
    final ASTNode[] changedElements = changeSet.getChangedElements();
    final CharTable table = ((FileElement) changeSet.getRootElement()).getCharTable();
    for (ASTNode changedElement : changedElements) {
        TreeChange changesByElement = changeSet.getChangesByElement(changedElement);
        PsiElement psiElement = null;
        while (changedElement != null && (psiElement = changedElement.getPsi()) == null) {
            final ASTNode parent = changedElement.getTreeParent();
            final ChangeInfoImpl changeInfo = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, changedElement);
            changeInfo.compactChange(changesByElement);
            changesByElement = new TreeChangeImpl(parent);
            changesByElement.addChange(changedElement, changeInfo);
            changedElement = parent;
        }
        if (changedElement == null)
            continue;
        final TreeChange finalChangedElement = changesByElement;
        psiElement.accept(new XmlElementVisitor() {

            TreeChange myChange = finalChangedElement;

            @Override
            public void visitElement(PsiElement element) {
                final ASTNode child = element.getNode();
                final ASTNode treeParent = child.getTreeParent();
                if (treeParent == null)
                    return;
                final PsiElement parent = treeParent.getPsi();
                final ChangeInfoImpl changeInfo = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, child);
                changeInfo.compactChange(myChange);
                myChange = new TreeChangeImpl(treeParent);
                myChange.addChange(child, changeInfo);
                parent.accept(this);
            }

            @Override
            public void visitXmlAttribute(XmlAttribute attribute) {
                final ASTNode[] affectedChildren = myChange.getAffectedChildren();
                String oldName = null;
                String oldValue = null;
                for (final ASTNode treeElement : affectedChildren) {
                    final ChangeInfo changeByChild = myChange.getChangeByChild(treeElement);
                    final int changeType = changeByChild.getChangeType();
                    if (treeElement.getElementType() == XmlTokenType.XML_NAME) {
                        if (changeType == ChangeInfo.REMOVED) {
                            oldName = treeElement.getText();
                        } else if (changeType == ChangeInfo.REPLACE) {
                            oldName = ((ReplaceChangeInfo) changeByChild).getReplaced().getText();
                        }
                    }
                    if (treeElement.getElementType() == XmlElementType.XML_ATTRIBUTE_VALUE) {
                        if (changeType == ChangeInfo.REMOVED) {
                            oldValue = treeElement.getText();
                        } else if (changeType == ChangeInfo.REPLACE) {
                            oldValue = ((ReplaceChangeInfo) changeByChild).getReplaced().getText();
                        }
                    }
                }
                if (oldName != null && !oldName.equals(attribute.getName())) {
                    xmlChangeSet.add(new XmlAttributeSetImpl(attribute.getParent(), oldName, null));
                    xmlChangeSet.add(new XmlAttributeSetImpl(attribute.getParent(), attribute.getName(), attribute.getValue()));
                } else if (oldValue != null) {
                    xmlChangeSet.add(new XmlAttributeSetImpl(attribute.getParent(), attribute.getName(), attribute.getValue()));
                } else {
                    xmlChangeSet.add(new XmlElementChangedImpl(attribute));
                }
            }

            @Override
            public void visitXmlTag(XmlTag tag) {
                ASTNode[] affectedChildren = shortenChange(myChange.getAffectedChildren(), changeSet);
                for (final ASTNode treeElement : affectedChildren) {
                    if (!(treeElement.getPsi() instanceof XmlTagChild)) {
                        visitElement(tag);
                        return;
                    }
                }
                for (final ASTNode treeElement : affectedChildren) {
                    final ChangeInfo changeByChild = myChange.getChangeByChild(treeElement);
                    final int changeType = changeByChild.getChangeType();
                    final IElementType type = treeElement.getElementType();
                    if (type == TokenType.WHITE_SPACE)
                        continue;
                    /*
            if (type == ElementType.XML_NAME) {
              final XmlToken xmlToken = (XmlToken)((ReplaceChangeInfo)changeByChild).getReplaced();
              xmlChangeSet.add(new XmlTagNameChangedImpl(tag, xmlToken.getText()));
              continue;
            }
            */
                    final PsiElement element = treeElement.getPsi();
                    switch(changeType) {
                        case ChangeInfo.ADD:
                            xmlChangeSet.add(new XmlTagChildAddImpl(tag, (XmlTagChild) element));
                            break;
                        case ChangeInfo.REMOVED:
                            treeElement.putUserData(CharTable.CHAR_TABLE_KEY, table);
                            xmlChangeSet.add(new XmlTagChildRemovedImpl(tag, (XmlTagChild) element));
                            break;
                        case ChangeInfo.CONTENTS_CHANGED:
                            xmlChangeSet.add(new XmlTagChildChangedImpl(tag, (XmlTagChild) element));
                            break;
                        case ChangeInfo.REPLACE:
                            final PsiElement psi = ((ReplaceChangeInfo) changeByChild).getReplaced().getPsi();
                            if (psi instanceof XmlTagChild) {
                                final XmlTagChild replaced = (XmlTagChild) psi;
                                replaced.putUserData(CharTable.CHAR_TABLE_KEY, table);
                                xmlChangeSet.add(new XmlTagChildRemovedImpl(tag, replaced));
                                xmlChangeSet.add(new XmlTagChildAddImpl(tag, (XmlTagChild) element));
                            }
                            break;
                    }
                }
            }

            @Override
            public void visitXmlDocument(XmlDocument document) {
                xmlChangeSet.clear();
                xmlChangeSet.add(new XmlDocumentChangedImpl(document));
            }

            @Override
            public void visitFile(PsiFile file) {
                final XmlDocument document = ((XmlFile) file).getDocument();
                if (document != null) {
                    xmlChangeSet.clear();
                    xmlChangeSet.add(new XmlDocumentChangedImpl(document));
                }
            }
        });
    }
}
Also used : TreeChangeEvent(com.intellij.pom.tree.events.TreeChangeEvent) ChangeInfoImpl(com.intellij.pom.tree.events.impl.ChangeInfoImpl) CharTable(com.intellij.util.CharTable) ASTNode(com.intellij.lang.ASTNode) PsiFile(com.intellij.psi.PsiFile) PsiElement(com.intellij.psi.PsiElement) XmlElementVisitor(com.intellij.psi.XmlElementVisitor) ReplaceChangeInfo(com.intellij.pom.tree.events.ReplaceChangeInfo) TreeChangeImpl(com.intellij.pom.tree.events.impl.TreeChangeImpl) ReplaceChangeInfo(com.intellij.pom.tree.events.ReplaceChangeInfo) ChangeInfo(com.intellij.pom.tree.events.ChangeInfo) IElementType(com.intellij.psi.tree.IElementType) TreeChange(com.intellij.pom.tree.events.TreeChange) FileElement(com.intellij.psi.impl.source.tree.FileElement)

Example 3 with CharTable

use of com.intellij.util.CharTable in project intellij-community by JetBrains.

the class XmlProcessingInstructionManipulator method handleContentChange.

@Override
public XmlProcessingInstruction handleContentChange(@NotNull XmlProcessingInstruction element, @NotNull TextRange range, String newContent) throws IncorrectOperationException {
    CheckUtil.checkWritable(element);
    final CompositeElement attrNode = (CompositeElement) element.getNode();
    final ASTNode valueNode = attrNode.findLeafElementAt(range.getStartOffset());
    LOG.assertTrue(valueNode != null, "Leaf not found in " + attrNode + " at offset " + range.getStartOffset() + " in element " + element);
    final PsiElement elementToReplace = valueNode.getPsi();
    String text;
    try {
        text = elementToReplace.getText();
        final int offsetInParent = elementToReplace.getStartOffsetInParent();
        String textBeforeRange = text.substring(0, range.getStartOffset() - offsetInParent);
        String textAfterRange = text.substring(range.getEndOffset() - offsetInParent, text.length());
        newContent = element.getText().startsWith("'") || element.getText().endsWith("'") ? newContent.replace("'", "'") : newContent.replace("\"", """);
        text = textBeforeRange + newContent + textAfterRange;
    } catch (StringIndexOutOfBoundsException e) {
        LOG.error("Range: " + range + " in text: '" + element.getText() + "'", e);
        throw e;
    }
    final CharTable charTableByTree = SharedImplUtil.findCharTableByTree(attrNode);
    final LeafElement newValueElement = Factory.createSingleLeafElement(XmlTokenType.XML_TAG_CHARACTERS, text, charTableByTree, element.getManager());
    attrNode.replaceChildInternal(valueNode, newValueElement);
    return element;
}
Also used : ASTNode(com.intellij.lang.ASTNode) CompositeElement(com.intellij.psi.impl.source.tree.CompositeElement) CharTable(com.intellij.util.CharTable) PsiElement(com.intellij.psi.PsiElement) LeafElement(com.intellij.psi.impl.source.tree.LeafElement)

Example 4 with CharTable

use of com.intellij.util.CharTable in project intellij-community by JetBrains.

the class FormatterUtil method replaceInnerWhiteSpace.

/**
   * There is a possible case that we want to adjust white space which is not represented at the AST/PSI tree, e.g.
   * we might have a multiline comment which uses tabs for inner lines indents and want to replace them by spaces.
   * There is no white space element then, the only leaf is the comment itself.
   * <p/>
   * This method allows such 'inner element modifications', i.e. it receives information on what new text should be used
   * at the target inner element range and performs corresponding replacement by generating new leaf with adjusted text
   * and replacing the old one by it.
   * 
   * @param newWhiteSpaceText  new text to use at the target inner element range
   * @param holder             target range holder
   * @param whiteSpaceRange    target range which text should be replaced by the given one
   */
public static void replaceInnerWhiteSpace(@NotNull final String newWhiteSpaceText, @NotNull final ASTNode holder, @NotNull final TextRange whiteSpaceRange) {
    final CharTable charTable = SharedImplUtil.findCharTableByTree(holder);
    StringBuilder newText = createNewLeafChars(holder, whiteSpaceRange, newWhiteSpaceText);
    LeafElement newElement = Factory.createSingleLeafElement(holder.getElementType(), newText, charTable, holder.getPsi().getManager());
    holder.getTreeParent().replaceChild(holder, newElement);
}
Also used : CharTable(com.intellij.util.CharTable)

Example 5 with CharTable

use of com.intellij.util.CharTable in project intellij-community by JetBrains.

the class MethodElement method deleteChildInternal.

@Override
public void deleteChildInternal(@NotNull ASTNode child) {
    if (child.getElementType() == CODE_BLOCK) {
        final ASTNode prevWS = TreeUtil.prevLeaf(child);
        if (prevWS != null && prevWS.getElementType() == TokenType.WHITE_SPACE) {
            removeChild(prevWS);
        }
        super.deleteChildInternal(child);
        final CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
        LeafElement semicolon = Factory.createSingleLeafElement(SEMICOLON, ";", 0, 1, treeCharTab, getManager());
        addInternal(semicolon, semicolon, null, Boolean.TRUE);
    } else {
        super.deleteChildInternal(child);
    }
}
Also used : ASTNode(com.intellij.lang.ASTNode) CharTable(com.intellij.util.CharTable)

Aggregations

CharTable (com.intellij.util.CharTable)35 ASTNode (com.intellij.lang.ASTNode)22 IElementType (com.intellij.psi.tree.IElementType)5 IncorrectOperationException (com.intellij.util.IncorrectOperationException)4 PsiElement (com.intellij.psi.PsiElement)3 PsiFile (com.intellij.psi.PsiFile)3 FileElement (com.intellij.psi.impl.source.tree.FileElement)3 FileASTNode (com.intellij.lang.FileASTNode)2 Language (com.intellij.lang.Language)2 LighterASTNode (com.intellij.lang.LighterASTNode)2 TextRange (com.intellij.openapi.util.TextRange)2 PsiClass (com.intellij.psi.PsiClass)2 DummyHolder (com.intellij.psi.impl.source.DummyHolder)2 LeafElement (com.intellij.psi.impl.source.tree.LeafElement)2 TreeElement (com.intellij.psi.impl.source.tree.TreeElement)2 NotNull (org.jetbrains.annotations.NotNull)2 PlainTextLanguage (com.intellij.openapi.fileTypes.PlainTextLanguage)1 Project (com.intellij.openapi.project.Project)1 Pair (com.intellij.openapi.util.Pair)1 PomModel (com.intellij.pom.PomModel)1