Skip to content

Commit bb68ddb

Browse files
committed
Remove NodeType.ROOT in favor of an implicit root
The root node is now implicitly characterised by having no parents (no after and no before parent). This makes it consistent with some representations of `DiffTree`s where the root node is printed as an IF node with the feature mapping `true`. All representations which did explicitly mark the root node are now printing an IF node and do not mark it specially. Most notably is the line graph representation which did encode `NodeType.ROOT` in the node ID (this is the reason why many IDs in the test cases changed). For backwards compatibility the `isAnnotation` function of `DiffNode` is still returning false on root nodes. This is subject to further refactoring, mostly necessary to handle the difference between `DiffGraph`s and actual trees.
1 parent a51723f commit bb68ddb

15 files changed

Lines changed: 70 additions & 92 deletions

src/main/java/org/variantsync/diffdetective/diff/difftree/DiffGraph.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,6 @@ public final class DiffGraph {
1212

1313
private DiffGraph() {}
1414

15-
/**
16-
* Returns true iff the given node has no parents (i.e., is a root candidate).
17-
*/
18-
public static boolean hasNoParents(final DiffNode node) {
19-
return node.getBeforeParent() == null && node.getAfterParent() == null;
20-
}
21-
2215
/**
2316
* Invokes {@link DiffGraph#fromNodes(Collection, DiffTreeSource)} )} with an unknown DiffTreeSource.
2417
*/
@@ -37,7 +30,7 @@ public static DiffTree fromNodes(final Collection<DiffNode> nodes, final DiffTre
3730
final DiffNode newRoot = DiffNode.createRoot();
3831
newRoot.setLabel(DIFFGRAPH_LABEL);
3932
nodes.stream()
40-
.filter(DiffGraph::hasNoParents)
33+
.filter(DiffNode::isRoot)
4134
.forEach(n ->
4235
n.diffType.matchBeforeAfter(
4336
() -> newRoot.addBeforeChild(n),

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public DiffNode(DiffType diffType, NodeType nodeType,
110110
public static DiffNode createRoot() {
111111
return new DiffNode(
112112
DiffType.NON,
113-
NodeType.ROOT,
113+
NodeType.IF,
114114
new DiffLineNumber(1, 1, 1),
115115
DiffLineNumber.Invalid(),
116116
FixTrueFalse.True,
@@ -968,17 +968,17 @@ public boolean isElse() {
968968
}
969969

970970
/**
971-
* Returns true if this node is a root node (i.e., it has {@link NodeType#ROOT}.
971+
* Returns true if this node is a root node (has no parents).
972972
*/
973973
public boolean isRoot() {
974-
return this.nodeType.equals(NodeType.ROOT);
974+
return getBeforeParent() == null && getAfterParent() == null;
975975
}
976976

977977
/**
978978
* Returns {@link NodeType#isAnnotation()} for this node's {@link DiffNode#nodeType}.
979979
*/
980980
public boolean isAnnotation() {
981-
return this.nodeType.isAnnotation();
981+
return this.nodeType.isAnnotation() && !this.isRoot();
982982
}
983983

984984
/**

src/main/java/org/variantsync/diffdetective/diff/difftree/NodeType.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@ public enum NodeType {
1515
ELIF("elif"),
1616

1717
// Artifact types
18-
ARTIFACT("artifact"),
19-
20-
// Extra type for the root
21-
ROOT("ROOT");
18+
ARTIFACT("artifact");
2219

2320
public final String name;
2421
NodeType(String name) {
@@ -36,7 +33,7 @@ public boolean isConditionalAnnotation() {
3633
* Returns true iff this node type represents a feature mapping.
3734
*/
3835
public boolean isAnnotation() {
39-
return this != ROOT && this != ARTIFACT;
36+
return this != ARTIFACT;
4037
}
4138

4239
final static Pattern annotationRegex = Pattern.compile("^[+-]?\\s*#\\s*(if|endif|else|elif)");

src/main/java/org/variantsync/diffdetective/diff/difftree/parse/DiffTreeParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ public static DiffNode popIf(final Stack<DiffNode> stack) {
274274
do {
275275
// Don't update line numbers of popped nodes here as this already happened.
276276
popped = stack.pop();
277-
} while (!popped.isIf() && !popped.isRoot());
277+
} while (!popped.isIf());
278278
return popped;
279279
}
280280

src/main/java/org/variantsync/diffdetective/diff/difftree/serialize/LineGraphImport.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,22 +129,20 @@ private static DiffTree parseDiffTree(final String lineGraph, final Path inFile,
129129

130130
// Handle trees and graphs differently
131131
if (options.graphFormat() == GraphFormat.DIFFGRAPH) {
132-
// If you should interpret the input data as DiffTrees, always expect a root to be present. Parse all nodes (v) to a list of nodes. Search for the root. Assert that there is exactly one root.
133-
Assert.assertTrue(diffNodeList.stream().noneMatch(DiffNode::isRoot)); // test if it’s not a tree
134132
return DiffGraph.fromNodes(diffNodeList, diffTreeSource);
135133
} else if (options.graphFormat() == GraphFormat.DIFFTREE) {
136134
// If you should interpret the input data as DiffTrees, always expect a root to be present. Parse all nodes (v) to a list of nodes. Search for the root. Assert that there is exactly one root.
137135
DiffNode root = null;
138136
for (final DiffNode v : diffNodeList) {
139-
if (DiffGraph.hasNoParents(v)) {
137+
if (v.isRoot()) {
140138
// v is root candidate
141139
if (root != null) {
142-
throw new RuntimeException("Not a DiffTree but a DiffGraph: Got more than one root! Got \"" + root + "\" and \"" + v + "\"!");
140+
throw new RuntimeException("Not a DiffTree: Got more than one root! Got \"" + root + "\" and \"" + v + "\"!");
143141
}
144-
if (v.nodeType == NodeType.IF || v.nodeType == NodeType.ROOT) {
142+
if (v.nodeType == NodeType.IF) {
145143
root = v;
146144
} else {
147-
throw new RuntimeException("Not a DiffTree but a DiffGraph: The node \"" + v + "\" is not labeled as ROOT or IF but has no parents!");
145+
throw new RuntimeException("Not a DiffTree but a DiffGraph: The node \"" + v + "\" is not labeled as IF but has no parents!");
148146
}
149147
}
150148
}

src/main/java/org/variantsync/diffdetective/diff/difftree/serialize/nodeformat/DiffNodeLabelPrettyfier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ private static String prettyPrintTypeAndMapping(final DiffNode node) {
3333
*/
3434
public static String prettyPrintIfAnnotationOr(final DiffNode node, final String elseValue) {
3535
String result = "";
36-
if (node.nodeType.isAnnotation()) {
36+
if (node.isAnnotation()) {
3737
result += prettyPrintTypeAndMapping(node);
3838
} else {
3939
result += elseValue;

src/main/java/org/variantsync/diffdetective/diff/difftree/transform/CollapseNestedNonEditedAnnotations.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ private static void collapseChain(Stack<DiffNode> chain) {
113113
lastPopped = chain.pop();
114114
}
115115
}
116-
case ROOT, ARTIFACT ->
116+
case ARTIFACT ->
117117
throw new RuntimeException("Unexpected node type " + lastPopped.nodeType + " within annotation chain!");
118118
case ENDIF -> {}
119119
}

src/main/java/org/variantsync/diffdetective/mining/RWCompositePatternNodeFormat.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public String toLabel(final DiffNode node) {
1111
return ProposedEditClasses.Instance.match(node).getName() + "<br>" + node.getLabel();
1212
} else {
1313
return node.diffType + "_" + switch (node.nodeType) {
14-
case ROOT -> "r";
1514
case IF -> "mapping<br> " + node.getLabel();
1615
case ELSE -> "else";
1716
case ELIF -> "elif<br>" + node.getLabel();

src/main/java/org/variantsync/diffdetective/mining/formats/DebugMiningDiffNodeFormat.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ public class DebugMiningDiffNodeFormat implements MiningNodeFormat {
1919
public String toLabel(final DiffNode node) {
2020
if (node.isArtifact()) {
2121
return ProposedEditClasses.Instance.match(node).getName();
22-
} else if (node.isRoot()) {
23-
return node.diffType + "_" + NodeType.IF;
2422
} else {
2523
return node.diffType + "_" + node.nodeType;
2624
}
@@ -34,9 +32,6 @@ public Pair<DiffType, NodeType> fromEncodedTypes(String tag) {
3432
final DiffType dt = DiffType.fromName(tag);
3533
final int nodeTypeBegin = tag.indexOf("_") + 1;
3634
final NodeType nt = NodeType.fromName(tag.substring(nodeTypeBegin));
37-
if (nt == NodeType.ROOT) {
38-
throw new IllegalArgumentException("There should be no roots in mined edit classes!");
39-
}
4035
return new Pair<>(dt, nt);
4136
} else {
4237
final EditClass editClass = ProposedEditClasses.Instance.fromName(tag).orElseThrow(

src/main/java/org/variantsync/diffdetective/mining/formats/ReleaseMiningDiffNodeFormat.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ public String toLabel(DiffNode node) {
4141
if (node.isArtifact()) {
4242
return ARTIFACT_PREFIX + toId(ProposedEditClasses.Instance.match(node));
4343
} else {
44-
final NodeType nodeType = node.isRoot() ? NodeType.IF : node.nodeType;
45-
return ANNOTATION_PREFIX + node.diffType.ordinal() + nodeType.ordinal();
44+
return ANNOTATION_PREFIX + node.diffType.ordinal() + node.nodeType.ordinal();
4645
}
4746
}
4847

@@ -61,9 +60,6 @@ public Pair<DiffType, NodeType> fromEncodedTypes(String tag) {
6160
final NodeType nodeType = NodeType.values()[Integer.parseInt(
6261
tag.substring(nodeTypeBegin, nodeTypeBegin + 1)
6362
)];
64-
if (nodeType == NodeType.ROOT) {
65-
throw new IllegalArgumentException("There should be no roots in mined edit classes!");
66-
}
6763
return new Pair<>(diffType, nodeType);
6864
}
6965
}

0 commit comments

Comments
 (0)