in src/main/com/intellij/lang/jsgraphql/types/util/NodeMultiZipper.java [139:198]
private NodeZipper<T> moveUp(T parent, List<NodeZipper<T>> sameParent) {
assertNotEmpty(sameParent, () -> "expected at least one zipper");
Map<String, List<T>> childrenMap = new HashMap<>(nodeAdapter.getNamedChildren(parent));
Map<String, Integer> indexCorrection = new HashMap<>();
sameParent = new ArrayList<>(sameParent);
sameParent.sort((zipper1, zipper2) -> {
int index1 = zipper1.getBreadcrumbs().get(0).getLocation().getIndex();
int index2 = zipper2.getBreadcrumbs().get(0).getLocation().getIndex();
if (index1 != index2) {
return Integer.compare(index1, index2);
}
NodeZipper.ModificationType modificationType1 = zipper1.getModificationType();
NodeZipper.ModificationType modificationType2 = zipper2.getModificationType();
// same index can never be deleted and changed at the same time
if (modificationType1 == modificationType2) {
return 0;
}
// always first replacing the node
if (modificationType1 == REPLACE) {
return -1;
}
// and then INSERT_BEFORE before INSERT_AFTER
return modificationType1 == NodeZipper.ModificationType.INSERT_BEFORE ? -1 : 1;
});
for (NodeZipper<T> zipper : sameParent) {
NodeLocation location = zipper.getBreadcrumbs().get(0).getLocation();
Integer ixDiff = indexCorrection.getOrDefault(location.getName(), 0);
int ix = location.getIndex() + ixDiff;
String name = location.getName();
List<T> childList = new ArrayList<>(childrenMap.get(name));
switch (zipper.getModificationType()) {
case REPLACE:
childList.set(ix, zipper.getCurNode());
break;
case DELETE:
childList.remove(ix);
indexCorrection.put(name, ixDiff - 1);
break;
case INSERT_BEFORE:
childList.add(ix, zipper.getCurNode());
indexCorrection.put(name, ixDiff + 1);
break;
case INSERT_AFTER:
childList.add(ix + 1, zipper.getCurNode());
indexCorrection.put(name, ixDiff + 1);
break;
}
childrenMap.put(name, childList);
}
T newNode = nodeAdapter.withNewChildren(parent, childrenMap);
List<Breadcrumb<T>> newBreadcrumbs = sameParent.get(0).getBreadcrumbs().subList(1, sameParent.get(0).getBreadcrumbs().size());
return new NodeZipper<>(newNode, newBreadcrumbs, this.nodeAdapter);
}