mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
PSI events: sort by element index which is more robust than current/initial offset
This commit is contained in:
@@ -145,8 +145,7 @@ public class TreeChangeEventImpl implements TreeChangeEvent{
|
||||
}
|
||||
|
||||
public void fireEvents() {
|
||||
Collection<TreeChangeImpl> changes = ContainerUtil.sorted(myChangedElements.values(),
|
||||
Comparator.comparing(TreeChangeImpl::getInitialStart));
|
||||
Collection<TreeChangeImpl> changes = ContainerUtil.sorted(myChangedElements.values());
|
||||
for (TreeChangeImpl change : changes) {
|
||||
change.fireEvents((PsiFile)myFileElement.getPsi());
|
||||
}
|
||||
|
||||
@@ -22,24 +22,23 @@ import com.intellij.pom.tree.events.TreeChange;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.source.tree.CompositeElement;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.JBIterable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class TreeChangeImpl implements TreeChange {
|
||||
public class TreeChangeImpl implements TreeChange, Comparable<TreeChangeImpl> {
|
||||
private final CompositeElement myParent;
|
||||
private final List<CompositeElement> mySuperParents;
|
||||
private final LinkedHashSet<TreeElement> myInitialChildren = new LinkedHashSet<>();
|
||||
private final Map<TreeElement, Integer> myInitialLengths = new HashMap<>();
|
||||
private final Set<TreeElement> myContentChangeChildren = new HashSet<>();
|
||||
private final int myInitialStart;
|
||||
private Map<TreeElement, ChangeInfoImpl> myChanges;
|
||||
|
||||
public TreeChangeImpl(@NotNull CompositeElement parent) {
|
||||
myParent = parent;
|
||||
mySuperParents = JBIterable.generate(parent.getTreeParent(), TreeElement::getTreeParent).toList();
|
||||
myInitialStart = myParent.getStartOffset();
|
||||
for (TreeElement child : getCurrentChildren()) {
|
||||
myInitialChildren.add(child);
|
||||
myInitialLengths.put(child, child.getTextLength());
|
||||
@@ -55,8 +54,29 @@ public class TreeChangeImpl implements TreeChange {
|
||||
return JBIterable.generate(myParent.getFirstChildNode(), TreeElement::getTreeNext);
|
||||
}
|
||||
|
||||
int getInitialStart() {
|
||||
return myInitialStart;
|
||||
@Override
|
||||
public int compareTo(@NotNull TreeChangeImpl o) {
|
||||
List<CompositeElement> thisParents = getSuperParents();
|
||||
List<CompositeElement> thatParents = o.getSuperParents();
|
||||
for (int i = 1; i <= thisParents.size() && i <= thatParents.size(); i++) {
|
||||
CompositeElement thisParent = i < thisParents.size() ? thisParents.get(thisParents.size() - i) : myParent;
|
||||
CompositeElement thatParent = i < thatParents.size() ? thatParents.get(thatParents.size() - i) : o.myParent;
|
||||
int result = compareNodePositions(thisParent, thatParent);
|
||||
if (result != 0) return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int compareNodePositions(CompositeElement node1, CompositeElement node2) {
|
||||
if (node1 == node2) return 0;
|
||||
|
||||
int o1 = node1.getStartOffsetInParent();
|
||||
int o2 = node2.getStartOffsetInParent();
|
||||
return o1 != o2 ? Integer.compare(o1, o2) : Integer.compare(getChildIndex(node1), getChildIndex(node2));
|
||||
}
|
||||
|
||||
private static int getChildIndex(CompositeElement e) {
|
||||
return ArrayUtil.indexOf(e.getTreeParent().getChildren(null), e);
|
||||
}
|
||||
|
||||
int getLengthDelta() {
|
||||
|
||||
@@ -78,6 +78,31 @@ class PsiEventConsistencyTest : LightPlatformCodeInsightFixtureTestCase() {
|
||||
assertEquals(root.text, file.viewProvider.document!!.text)
|
||||
}
|
||||
}
|
||||
|
||||
fun `test changes in different AST parents at the same initial offset`() {
|
||||
val file = createEmptyFile()
|
||||
WriteCommandAction.runWriteCommandAction(project) {
|
||||
//prepare
|
||||
val root = file.node as FileElement
|
||||
root.replaceChild(root.firstChildNode, composite(compositeTypes[0],
|
||||
composite(compositeTypes[0]),
|
||||
composite(compositeTypes[0], leaf(leafTypes[0], "x")),
|
||||
composite(compositeTypes[0], leaf(leafTypes[0], "s"))))
|
||||
|
||||
ChangeUtil.prepareAndRunChangeAction(ChangeUtil.ChangeAction {
|
||||
val pComposite = root.firstChildNode.firstChildNode
|
||||
val xComposite = pComposite.treeNext
|
||||
val sComposite = xComposite.treeNext
|
||||
sComposite.replaceChild(sComposite.firstChildNode, leaf(leafTypes[0], "h"))
|
||||
ChangeUtil.prepareAndRunChangeAction(ChangeUtil.ChangeAction {
|
||||
pComposite.addChild(leaf(leafTypes[0], "p"))
|
||||
xComposite.removeChild(xComposite.firstChildNode)
|
||||
}, root)
|
||||
}, root)
|
||||
assertEquals("ph", root.text)
|
||||
assertEquals(root.text, file.viewProvider.document!!.text)
|
||||
}
|
||||
}
|
||||
|
||||
fun testPsiDocSynchronization() {
|
||||
PropertyChecker.forAll(commands).shouldHold { cmd ->
|
||||
|
||||
Reference in New Issue
Block a user