use of com.intellij.pom.tree.events.ChangeInfo 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));
}
}
});
}
}
use of com.intellij.pom.tree.events.ChangeInfo in project intellij-community by JetBrains.
the class TreeChangeImpl method add.
@Override
public void add(@NotNull final TreeChange value) {
final TreeChangeImpl impl = (TreeChangeImpl) value;
LOG.assertTrue(impl.myParent == myParent);
for (final Pair<ASTNode, Integer> pair : impl.mySortedChanges) {
final ASTNode child = pair.getFirst();
ChangeInfo change = impl.myChanges.get(child);
if (change.getChangeType() == ChangeInfo.REMOVED) {
final ChangeInfo oldChange = myChanges.get(child);
if (oldChange != null) {
switch(oldChange.getChangeType()) {
case ChangeInfo.ADD:
removeChangeInternal(child);
break;
case ChangeInfo.REPLACE:
final ASTNode replaced = ((ReplaceChangeInfo) oldChange).getReplaced();
removeChangeInternal(child);
myChanges.put(replaced, ChangeInfoImpl.create(ChangeInfo.REMOVED, replaced));
addChangeAtOffset(replaced, getOldOffset(pair.getSecond().intValue()));
break;
case ChangeInfo.CONTENTS_CHANGED:
((ChangeInfoImpl) change).setOldLength(oldChange.getOldLength());
myChanges.put(child, change);
break;
}
} else {
myChanges.put(child, change);
addChangeAtOffset(child, getOldOffset(pair.getSecond().intValue()));
}
} else if (change.getChangeType() == ChangeInfo.REPLACE) {
ReplaceChangeInfo replaceChangeInfo = (ReplaceChangeInfo) change;
final ASTNode replaced = replaceChangeInfo.getReplaced();
final ChangeInfo oldChange = myChanges.get(replaced);
if (oldChange != null) {
switch(oldChange.getChangeType()) {
case ChangeInfo.ADD:
change = ChangeInfoImpl.create(ChangeInfo.ADD, child);
break;
case ChangeInfo.CONTENTS_CHANGED:
((ChangeInfoImpl) change).setOldLength(oldChange.getOldLength());
break;
case ChangeInfo.REPLACE:
final ASTNode oldReplaced = ((ReplaceChangeInfo) oldChange).getReplaced();
ReplaceChangeInfoImpl rep = new ReplaceChangeInfoImpl(child);
rep.setReplaced(oldReplaced);
change = rep;
break;
}
removeChangeInternal(replaced);
}
addChange(child, change);
} else {
addChange(child, change);
}
}
}
use of com.intellij.pom.tree.events.ChangeInfo in project intellij-community by JetBrains.
the class TreeChangeImpl method getOptimizedNodeOldOffset.
private int getOptimizedNodeOldOffset(ASTNode child, ChangeInfo changeInfo) {
// we usually add / remove ranges so old offset can be tried to calculate from change with previous sibling
ASTNode prevSibling = child.getTreePrev();
if (prevSibling != null) {
if (mySortedChanges.size() > 0) {
Pair<ASTNode, Integer> pair = mySortedChanges.get(mySortedChanges.size() - 1);
if (pair.getFirst() == prevSibling) {
ChangeInfo prevSiblingChange = myChanges.get(prevSibling);
if ((prevSiblingChange.getChangeType() == ChangeInfo.REMOVED && changeInfo.getChangeType() == ChangeInfo.REMOVED) || (prevSiblingChange.getChangeType() == ChangeInfo.ADD && changeInfo.getChangeType() == ChangeInfo.ADD)) {
int optimizedResult = pair.getSecond() + prevSiblingChange.getOldLength();
if (ourDoChecks && !ourReportedDifferentOptimizedNodeOldOffset) {
int oldOffset = calculateOldOffsetLinearly(child);
if (optimizedResult != oldOffset) {
LOG.error("Failed optimized node old offset check:" + changeInfo + ", previous:" + prevSibling + "," + prevSiblingChange);
ourReportedDifferentOptimizedNodeOldOffset = true;
optimizedResult = oldOffset;
}
}
return optimizedResult;
}
}
}
}
return haveNotCalculated;
}
use of com.intellij.pom.tree.events.ChangeInfo in project intellij-community by JetBrains.
the class TreeChangeImpl method getOldOffset.
private int getOldOffset(int offset) {
for (Pair<ASTNode, Integer> pair : mySortedChanges) {
if (pair.getSecond() > offset)
break;
final ChangeInfo change = myChanges.get(pair.getFirst());
offset += change.getOldLength() - getNewLength(change, pair.getFirst());
}
return offset;
}
use of com.intellij.pom.tree.events.ChangeInfo in project intellij-community by JetBrains.
the class TreeChangeImpl method addChange.
@Override
public void addChange(ASTNode child, @NotNull ChangeInfo changeInfo) {
LOG.assertTrue(child.getTreeParent() == myParent);
final ChangeInfo current = myChanges.get(child);
if (current != null && changeInfo.getChangeType() == ChangeInfo.CONTENTS_CHANGED) {
return;
}
if (changeInfo.getChangeType() == ChangeInfo.REPLACE) {
final ReplaceChangeInfoImpl replaceChangeInfo = (ReplaceChangeInfoImpl) changeInfo;
final ASTNode replaced = replaceChangeInfo.getReplaced();
final ChangeInfo replacedInfo = myChanges.get(replaced);
if (replacedInfo == null) {
addChangeInternal(child, changeInfo);
} else {
switch(replacedInfo.getChangeType()) {
case ChangeInfo.REPLACE:
replaceChangeInfo.setOldLength(replacedInfo.getOldLength());
replaceChangeInfo.setReplaced(((ReplaceChangeInfo) replacedInfo).getReplaced());
break;
case ChangeInfo.ADD:
changeInfo = ChangeInfoImpl.create(ChangeInfo.ADD, replaced);
removeChangeInternal(replaced);
break;
}
addChangeInternal(child, changeInfo);
}
return;
}
if (current != null && current.getChangeType() == ChangeInfo.REMOVED) {
if (changeInfo.getChangeType() == ChangeInfo.ADD) {
if (!(child instanceof LeafElement)) {
// remove/add -> changed
changeInfo = ChangeInfoImpl.create(ChangeInfo.CONTENTS_CHANGED, child);
((ChangeInfoImpl) changeInfo).setOldLength(current.getOldLength());
myChanges.put(child, changeInfo);
} else {
removeChangeInternal(child);
}
}
return;
}
// add + remove == no op
if (current != null && current.getChangeType() == ChangeInfo.ADD) {
if (changeInfo.getChangeType() == ChangeInfo.REMOVED) {
removeChangeInternal(child);
}
return;
}
if (changeInfo.getChangeType() == ChangeInfo.REMOVED) {
if (child instanceof LeafElement) {
final CharSequence charTabIndex = child.getChars();
if (checkLeaf(child.getTreeNext(), charTabIndex) || checkLeaf(child.getTreePrev(), charTabIndex))
return;
}
addChangeInternal(child, changeInfo);
if (current != null) {
((ChangeInfoImpl) changeInfo).setOldLength(current.getOldLength());
}
return;
}
if (current == null) {
addChangeInternal(child, changeInfo);
}
}
Aggregations