Skip to content

Commit 0094462

Browse files
authored
Merge pull request #177 from VariantSync/assert-at-most-one-else
Assert that there is at most one else in `assertConsistency`
2 parents 047df57 + 9f43cc9 commit 0094462

File tree

4 files changed

+53
-36
lines changed

4 files changed

+53
-36
lines changed

src/main/java/org/variantsync/diffdetective/variation/diff/DiffNode.java

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -733,10 +733,14 @@ public static DiffNode<DiffLinesLabel> fromID(int id, String label) {
733733
* Checks that the VariationDiff is in a valid state.
734734
* In particular, this method checks that all edges are well-formed (e.g., edges can be inconsistent because edges are double-linked).
735735
* This method also checks that a node with exactly one parent was edited, and that a node with exactly two parents was not edited.
736+
* To check all children recursively, use {@link VariationDiff#assertConsistency}.
736737
* @see Assert#assertTrue
737738
* @throws AssertionError when an inconsistency is detected.
738739
*/
739740
public void assertConsistency() {
741+
// check that the projections are valid (i.e., node type specific consistency checks)
742+
diffType.forAllTimesOfExistence(time -> this.projection(time).assertConsistency());
743+
740744
// check consistency of children lists and edges
741745
for (final DiffNode<L> c : getAllChildren()) {
742746
Assert.assertTrue(isChild(c), () -> "Child " + c + " of " + this + " is neither a before nor an after child!");
@@ -760,6 +764,10 @@ public void assertConsistency() {
760764
if (pb != null && pa == null) {
761765
Assert.assertTrue(isRem());
762766
}
767+
// the root was not edited
768+
if (pb == null && pa == null) {
769+
Assert.assertTrue(isNon());
770+
}
763771
// a node with exactly two parents was not edited
764772
if (pb != null && pa != null) {
765773
Assert.assertTrue(isNon());
@@ -770,22 +778,6 @@ public void assertConsistency() {
770778
Assert.assertTrue(pb.isNon());
771779
}
772780
}
773-
774-
// Else and Elif nodes have an If or Elif as parent.
775-
if (this.isElse() || this.isElif()) {
776-
Time.forAll(time -> {
777-
if (getParent(time) != null) {
778-
Assert.assertTrue(getParent(time).isIf() || getParent(time).isElif(), time + " parent " + getParent(time) + " of " + this + " is neither IF nor ELIF!");
779-
}
780-
});
781-
}
782-
783-
// Only if and elif nodes have a formula
784-
if (this.isIf() || this.isElif()) {
785-
Assert.assertTrue(this.getFormula() != null, "If or elif without feature mapping!");
786-
} else {
787-
Assert.assertTrue(this.getFormula() == null, "Node with type " + getNodeType() + " has a non null feature mapping");
788-
}
789781
}
790782

791783
/**

src/main/java/org/variantsync/diffdetective/variation/diff/Projection.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,9 @@ public Node getFormula() {
130130
public int getID() {
131131
return getBackingNode().getID();
132132
}
133+
134+
@Override
135+
public String toString() {
136+
return String.format("Projection(%s, %s)", time, getBackingNode());
137+
}
133138
};

src/main/java/org/variantsync/diffdetective/variation/tree/VariationNode.java

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -487,26 +487,28 @@ public VariationTreeNode<L> toVariationTree(final Map<? super T, VariationTreeNo
487487
}
488488

489489
/**
490-
* Checks that this node satisfies some easy to check invariants.
491-
* In particular, this method checks that
492-
* <ul>
493-
* <li>if-chains are nested correctly,
494-
* <li>the root is an {@link NodeType#IF} with the feature mapping {@code "true"},
495-
* <li>the feature mapping is {@code null} iff {@code isConditionalAnnotation} is {@code false}
496-
* and
497-
* <li>all edges are well-formed (e.g., edges can be inconsistent because edges are
498-
* double-linked).
499-
* </ul>
500-
*
501-
* <p>Some invariants are not checked. These include
502-
* <ul>
503-
* <li>There should be no cycles and
504-
* <li>{@link getID} should be unique in the whole variation tree.
505-
* </ul>
506-
*
507-
* @see Assert#assertTrue
508-
* @throws AssertionError when an inconsistency is detected.
509-
*/
490+
* Checks that this node satisfies some easy to check invariants.
491+
* In particular, this method checks that
492+
* <ul>
493+
* <li>if-chains are nested correctly,
494+
* <li>the root is an {@link NodeType#IF} with the feature mapping {@code "true"},
495+
* <li>the feature mapping is {@code null} iff {@code isConditionalAnnotation} is {@code false}
496+
* and
497+
* <li>all edges are well-formed (e.g., edges can be inconsistent because edges are
498+
* double-linked).
499+
* </ul>
500+
*
501+
* <p>Some invariants are not checked. These include
502+
* <ul>
503+
* <li>There should be no cycles,
504+
* <li>{@link getID} should be unique in the whole variation tree, and
505+
* <li>children are not checked recursively.
506+
* </ul>
507+
* Use {@link VariationTree#assertConsistency} to check all children recursively.
508+
*
509+
* @see Assert#assertTrue
510+
* @throws AssertionError when an inconsistency is detected.
511+
*/
510512
public void assertConsistency() {
511513
// ELSE and ELIF nodes have an IF or ELIF as parent.
512514
if (isElse() || isElif()) {
@@ -537,6 +539,12 @@ public void assertConsistency() {
537539
"The root has to have the feature mapping 'true'");
538540
}
539541

542+
// check that there is at most one ELIF/ELSE
543+
Assert.assertTrue(
544+
getChildren().stream().filter(c -> c.isElif() || c.isElse()).count() <= 1,
545+
"There is more than one ELIF/ELSE node."
546+
);
547+
540548
// check consistency of children lists and edges
541549
for (var child : getChildren()) {
542550
Assert.assertTrue(

src/main/java/org/variantsync/diffdetective/variation/tree/VariationTree.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.variantsync.diffdetective.util.Assert;
66
import org.variantsync.diffdetective.variation.DiffLinesLabel;
77
import org.variantsync.diffdetective.variation.Label;
8+
import org.variantsync.diffdetective.variation.NodeType; // For Javadoc
89
import org.variantsync.diffdetective.variation.diff.DiffNode;
910
import org.variantsync.diffdetective.variation.diff.VariationDiff;
1011
import org.variantsync.diffdetective.variation.diff.Projection;
@@ -213,6 +214,17 @@ public String unparse() {
213214
return result.toString();
214215
}
215216

217+
/**
218+
* Checks whether this {@link VariationTree} is consistent.
219+
* Throws an error if this {@link VariationTree} is inconsistent (e.g., if there are multiple
220+
* {@link NodeType#ELSE} nodes). Has no side-effects otherwise.
221+
*
222+
* @see VariationNode#assertConsistency
223+
*/
224+
public void assertConsistency() {
225+
forAllPreorder(VariationTreeNode::assertConsistency);
226+
}
227+
216228
@Override
217229
public String toString() {
218230
return "variation tree from " + source;

0 commit comments

Comments
 (0)