Search in sources :

Example 1 with TreeChange

use of com.intellij.pom.tree.events.TreeChange 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 2 with TreeChange

use of com.intellij.pom.tree.events.TreeChange in project intellij-community by JetBrains.

the class TreeChangeEventImpl method processElementaryChange.

private void processElementaryChange(ASTNode parent, ASTNode element, ChangeInfo change, int depth) {
    TreeChange treeChange = myChangedElements.get(parent);
    if (treeChange == null) {
        treeChange = new TreeChangeImpl(parent);
        myChangedElements.put(parent, treeChange);
        final int index = depth >= 0 ? depth : getDepth(parent);
        addToEqualsDepthList(index, parent);
    }
    treeChange.addChange(element, change);
    if (change.getChangeType() == ChangeInfo.REMOVED) {
        element.putUserData(CharTable.CHAR_TABLE_KEY, myFileElement.getCharTable());
    }
    if (treeChange.isEmpty())
        removeAssociatedChanges(parent, depth);
}
Also used : TreeChange(com.intellij.pom.tree.events.TreeChange)

Example 3 with TreeChange

use of com.intellij.pom.tree.events.TreeChange in project intellij-community by JetBrains.

the class TreeChangeEventImpl method compactChanges.

private void compactChanges(ASTNode parent, int depth) {
    int currentDepth = myOfEqualDepth.size();
    while (--currentDepth > depth) {
        final Set<ASTNode> treeElements = myOfEqualDepth.get(currentDepth);
        if (treeElements == null)
            continue;
        final Iterator<ASTNode> iterator = treeElements.iterator();
        while (iterator.hasNext()) {
            boolean isUnderCompacted = false;
            final TreeElement treeElement = (TreeElement) iterator.next();
            ASTNode currentParent = treeElement;
            while (currentParent != null) {
                if (currentParent == parent) {
                    isUnderCompacted = true;
                    break;
                }
                currentParent = currentParent.getTreeParent();
            }
            if (isUnderCompacted) {
                final ChangeInfoImpl compactedChange = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, treeElement);
                compactedChange.compactChange(getChangesByElement(treeElement));
                iterator.remove();
                removeAssociatedChanges(treeElement, currentDepth);
                final CompositeElement treeParent = treeElement.getTreeParent();
                final TreeChange changesByElement = getChangesByElement(treeParent);
                if (changesByElement != null) {
                    final ChangeInfoImpl changeByChild = (ChangeInfoImpl) changesByElement.getChangeByChild(treeElement);
                    if (changeByChild != null) {
                        changeByChild.setOldLength(compactedChange.getOldLength());
                    } else {
                        changesByElement.addChange(treeElement, compactedChange);
                    }
                } else {
                    processElementaryChange(treeParent, treeElement, compactedChange, currentDepth - 1);
                }
            }
        }
    }
}
Also used : TreeChange(com.intellij.pom.tree.events.TreeChange) ASTNode(com.intellij.lang.ASTNode) CompositeElement(com.intellij.psi.impl.source.tree.CompositeElement) TreeElement(com.intellij.psi.impl.source.tree.TreeElement)

Example 4 with TreeChange

use of com.intellij.pom.tree.events.TreeChange in project intellij-community by JetBrains.

the class TreeChangeEventImpl method addElementaryChange.

@Override
public void addElementaryChange(@NotNull ASTNode element, @NotNull ChangeInfo change) {
    LOG.assertTrue(isAncestor(element, myFileElement), element);
    final ASTNode parent = element.getTreeParent();
    if (parent == null)
        return;
    ASTNode currentParent = parent;
    ASTNode prevParent = element;
    int depth = 0;
    while (currentParent != null) {
        if (myChangedElements.containsKey(currentParent)) {
            final TreeChange changesByElement = getChangesByElement(currentParent);
            final boolean currentParentHasChange = changesByElement.getChangeByChild(prevParent) != null;
            if (currentParentHasChange && prevParent != element)
                return;
            if (prevParent != element) {
                final ChangeInfo newChange = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, prevParent);
                if (change.getChangeType() != ChangeInfo.REMOVED) {
                    ((ChangeInfoImpl) newChange).processElementaryChange(change, element);
                }
                change = newChange;
            }
            processElementaryChange(currentParent, prevParent, change, -1);
            return;
        }
        depth++;
        prevParent = currentParent;
        currentParent = currentParent.getTreeParent();
    }
    compactChanges(parent, depth - 1);
    processElementaryChange(parent, element, change, depth - 1);
}
Also used : TreeChange(com.intellij.pom.tree.events.TreeChange) ChangeInfo(com.intellij.pom.tree.events.ChangeInfo) ASTNode(com.intellij.lang.ASTNode)

Example 5 with TreeChange

use of com.intellij.pom.tree.events.TreeChange in project intellij-community by JetBrains.

the class PsiEventWrapperAspect method sendAfterEvents.

private static void sendAfterEvents(TreeChangeEvent changeSet) {
    ASTNode rootElement = changeSet.getRootElement();
    final PsiFile file = (PsiFile) SourceTreeToPsiMap.treeElementToPsi(rootElement);
    final PsiManagerImpl manager = (PsiManagerImpl) file.getManager();
    if (manager == null)
        return;
    if (!file.isPhysical()) {
        manager.afterChange(false);
        return;
    }
    final ASTNode[] changedElements = changeSet.getChangedElements();
    for (ASTNode changedElement : changedElements) {
        TreeChange changesByElement = changeSet.getChangesByElement(changedElement);
        PsiElement psiParent = null;
        while (changedElement != null && ((psiParent = changedElement.getPsi()) == null || !checkPsiForChildren(changesByElement.getAffectedChildren()))) {
            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 ASTNode[] affectedChildren = changesByElement.getAffectedChildren();
        for (final ASTNode treeElement : affectedChildren) {
            PsiTreeChangeEventImpl psiEvent = new PsiTreeChangeEventImpl(manager);
            psiEvent.setParent(psiParent);
            psiEvent.setFile(file);
            final PsiElement psiChild = treeElement.getPsi();
            psiEvent.setChild(psiChild);
            final ChangeInfo changeByChild = changesByElement.getChangeByChild(treeElement);
            switch(changeByChild.getChangeType()) {
                case ChangeInfo.ADD:
                    psiEvent.setOffset(treeElement.getStartOffset());
                    psiEvent.setOldLength(0);
                    manager.childAdded(psiEvent);
                    break;
                case ChangeInfo.REPLACE:
                    final ReplaceChangeInfo change = (ReplaceChangeInfo) changeByChild;
                    psiEvent.setOffset(treeElement.getStartOffset());
                    final ASTNode replaced = change.getReplaced();
                    psiEvent.setOldChild(replaced.getPsi());
                    psiEvent.setNewChild(psiChild);
                    psiEvent.setOldLength(replaced.getTextLength());
                    manager.childReplaced(psiEvent);
                    break;
                case ChangeInfo.CONTENTS_CHANGED:
                    psiEvent.setOffset(treeElement.getStartOffset());
                    psiEvent.setParent(psiChild);
                    psiEvent.setOldLength(changeByChild.getOldLength());
                    manager.childrenChanged(psiEvent);
                    break;
                case ChangeInfo.REMOVED:
                    psiEvent.setOffset(changesByElement.getChildOffsetInNewTree(treeElement));
                    psiEvent.setOldParent(psiParent);
                    psiEvent.setOldChild(psiChild);
                    psiEvent.setOldLength(changeByChild.getOldLength());
                    manager.childRemoved(psiEvent);
                    break;
            }
        }
    }
}
Also used : ReplaceChangeInfo(com.intellij.pom.tree.events.ReplaceChangeInfo) PsiManagerImpl(com.intellij.psi.impl.PsiManagerImpl) TreeChange(com.intellij.pom.tree.events.TreeChange) TreeChangeImpl(com.intellij.pom.tree.events.impl.TreeChangeImpl) ReplaceChangeInfo(com.intellij.pom.tree.events.ReplaceChangeInfo) ChangeInfo(com.intellij.pom.tree.events.ChangeInfo) ASTNode(com.intellij.lang.ASTNode) ChangeInfoImpl(com.intellij.pom.tree.events.impl.ChangeInfoImpl) PsiFile(com.intellij.psi.PsiFile) PsiTreeChangeEventImpl(com.intellij.psi.impl.PsiTreeChangeEventImpl) PsiElement(com.intellij.psi.PsiElement)

Aggregations

TreeChange (com.intellij.pom.tree.events.TreeChange)5 ASTNode (com.intellij.lang.ASTNode)4 ChangeInfo (com.intellij.pom.tree.events.ChangeInfo)3 ReplaceChangeInfo (com.intellij.pom.tree.events.ReplaceChangeInfo)2 ChangeInfoImpl (com.intellij.pom.tree.events.impl.ChangeInfoImpl)2 TreeChangeImpl (com.intellij.pom.tree.events.impl.TreeChangeImpl)2 PsiElement (com.intellij.psi.PsiElement)2 PsiFile (com.intellij.psi.PsiFile)2 TreeChangeEvent (com.intellij.pom.tree.events.TreeChangeEvent)1 XmlElementVisitor (com.intellij.psi.XmlElementVisitor)1 PsiManagerImpl (com.intellij.psi.impl.PsiManagerImpl)1 PsiTreeChangeEventImpl (com.intellij.psi.impl.PsiTreeChangeEventImpl)1 CompositeElement (com.intellij.psi.impl.source.tree.CompositeElement)1 FileElement (com.intellij.psi.impl.source.tree.FileElement)1 TreeElement (com.intellij.psi.impl.source.tree.TreeElement)1 IElementType (com.intellij.psi.tree.IElementType)1 CharTable (com.intellij.util.CharTable)1