1-
21package org .variantsync .diffdetective .variation .diff .transform ;
32
43import org .prop4j .Node ;
5- import org .variantsync .diffdetective .variation .Label ;
4+ import org .prop4j .NodeWriter ;
5+ import org .variantsync .diffdetective .util .Assert ;
6+ import org .variantsync .diffdetective .util .StringUtils ;
7+ import org .variantsync .diffdetective .variation .DiffLinesLabel ;
8+ import static org .variantsync .diffdetective .variation .DiffLinesLabel .Line ;
69import org .variantsync .diffdetective .variation .tree .VariationTree ;
710import org .variantsync .diffdetective .variation .tree .VariationTreeNode ;
811
3538 *
3639 * @author Paul Bittner
3740 */
38- public class EliminateEmptyAlternatives <L extends Label > implements Transformer <VariationTree <L >> {
39- private void elim (VariationTreeNode <L > subtree ) {
41+ public class EliminateEmptyAlternatives implements Transformer <VariationTree <DiffLinesLabel >> {
42+ /**
43+ * Creates a copy of the given label but where the formula is set to the given formula.
44+ * This method also updates the text in the DiffLinesLabel accordingly so that the text is
45+ * consistent with the formula.
46+ * This method assumes that the label has at least one line of text, otherwise the given label
47+ * could not have a formula.
48+ */
49+ private static DiffLinesLabel updatedLabel (DiffLinesLabel l , Node formula ) {
50+ final List <Line > lines = l .getDiffLines ();
51+ Assert .assertFalse (lines .isEmpty ());
52+
53+ // Assumption:
54+ // The only case in which there is more than one line of text is, when we parsed a multiline macro.
55+ //
56+ // We hence may safely ignore any subsequent lines from our existing label because these correspond
57+ // only to lines of a multiline macro, which we ought to replace anyway.
58+ final Line head = lines .get (0 );
59+ Assert .assertTrue (head .content ().contains ("if" ));
60+ final String indent = StringUtils .getLeadingWhitespace (head .content ());
61+
62+ final String newText = indent + "#if " + formula .toString (NodeWriter .javaSymbols );
63+
64+ // We might have replaced multiple lines by a single line here.
65+ // In this case, some line numbers got lost and any variation tree using this updated label somewhere might not
66+ // have consecutive line numbering anymore. We could consider inserting empty lines to retain
67+ // consecutive line numbers but that might be a more artifical change than inconsecutive line numbers.
68+ return new DiffLinesLabel (
69+ List .of (new Line (newText , head .lineNumber ())),
70+ l .getDiffTrailingLines ()
71+ );
72+ }
73+
74+ private static void elim (VariationTreeNode <DiffLinesLabel > subtree ) {
4075 // We simplify only annotations.
4176 if (!subtree .isAnnotation ()) return ;
4277
43- final List <VariationTreeNode <L >> children = subtree .getChildren ();
78+ final List <VariationTreeNode <DiffLinesLabel >> children = subtree .getChildren ();
4479
4580 // When there are no children, 'subtree' is an empty annotation that can be eliminated.
4681 if (children .isEmpty ()) {
4782 subtree .drop ();
4883 }
4984 // When there is exactly one child and that child is an 'else' or 'elif' we can simplify that nesting.
5085 else if (children .size () == 1 ) {
51- final VariationTreeNode <L > child = children .getFirst ();
86+ final VariationTreeNode <DiffLinesLabel > child = children .getFirst ();
5287
5388 if ((subtree .isIf () || subtree .isElif ()) && (child .isElif () || child .isElse ())) {
5489 // determine new feaure mapping
@@ -57,6 +92,7 @@ else if (children.size() == 1) {
5792 newFormula = and (newFormula , child .getFormula ());
5893 }
5994 subtree .setFormula (newFormula );
95+ subtree .setLabel (updatedLabel (subtree .getLabel (), newFormula ));
6096
6197 // simplify tree
6298 child .drop ();
@@ -66,7 +102,7 @@ else if (children.size() == 1) {
66102 }
67103
68104 @ Override
69- public void transform (VariationTree <L > tree ) {
70- tree .forAllPostorder (this ::elim );
105+ public void transform (VariationTree <DiffLinesLabel > tree ) {
106+ tree .forAllPostorder (EliminateEmptyAlternatives ::elim );
71107 }
72108}
0 commit comments