ListRemovalChange.java
/*
* Copyright (C) 2007-2010 J��lio Vilmar Gesser.
* Copyright (C) 2011, 2013-2024 The JavaParser Team.
*
* This file is part of JavaParser.
*
* JavaParser can be used either under the terms of
* a) the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* b) the terms of the Apache License
*
* You should have received a copy of both licenses in LICENCE.LGPL and
* LICENCE.APACHE. Please refer to those files for details.
*
* JavaParser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
package com.github.javaparser.printer.lexicalpreservation.changes;
import com.github.javaparser.Range;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.observer.ObservableProperty;
import java.util.Optional;
/**
* The removal of an element from a list.
*/
public class ListRemovalChange implements Change {
private final ObservableProperty observableProperty;
private final int index;
public ListRemovalChange(ObservableProperty observableProperty, int index) {
this.observableProperty = observableProperty;
this.index = index;
}
@Override
public Object getValue(ObservableProperty property, Node node) {
if (property == observableProperty) {
Object currentRawValue = new NoChange().getValue(property, node);
if (currentRawValue instanceof Optional) {
Optional<?> optional = (Optional<?>) currentRawValue;
currentRawValue = optional.orElse(null);
}
if (!(currentRawValue instanceof NodeList)) {
throw new IllegalStateException(
"Expected NodeList, found " + currentRawValue.getClass().getCanonicalName());
}
NodeList<Node> currentNodeList = (NodeList<Node>) currentRawValue;
// Note: When adding to a node list children get assigned the list's parent, thus we must set the list's
// parent before adding children (#2592).
NodeList<Node> newNodeList = new NodeList<>();
// fix #2187 set the parent node in the new list
newNodeList.setParentNode(currentNodeList.getParentNodeForChildren());
// Here we want to obtain a sub-list that does not contain an element.
// It is important not to implement this by first adding all the elements in the
// list and then deleting the element to be removed, as this involves event
// propagation mechanisms, particularly for lexical preservation,
// which deletes the relationship between a node and its parent node.
// This relationship is necessary to reinforce indentation, for example when
// deleting a node, as indentation can be carried by the parent node.
currentNodeList.stream()
.filter(n -> !isSameNode(currentNodeList.get(index), n))
.forEach(selectedNode -> newNodeList.add(selectedNode));
return newNodeList;
}
return new NoChange().getValue(property, node);
}
private boolean isSameNode(Node n1, Node n2) {
return n1.equals(n2) && isSameRange(n1, n2);
}
private boolean isSameRange(Node n1, Node n2) {
return (!n1.hasRange() && !n2.hasRange())
|| (n1.hasRange()
&& n2.hasRange()
&& isSameRange(n1.getRange().get(), n2.getRange().get()));
}
private boolean isSameRange(Range r1, Range r2) {
return r1.equals(r2);
}
@Override
public ObservableProperty getProperty() {
return observableProperty;
}
}