Class DiffNode<L extends Label>
java.lang.Object
org.variantsync.diffdetective.variation.diff.DiffNode<L>
- Type Parameters:
L- The type of label stored in this node.
- All Implemented Interfaces:
HasNodeType
Implementation of a node in a
VariationDiff.
A DiffNode represents a single node within a variation tree diff (according to our ESEC/FSE'22 paper), but is specialized
to the target domain of preprocessor-based software product lines.
Thus, opposed to the generic mathematical model of variation tree diffs, a DiffNode always stores lines of text, line numbers, and child ordering information as its label.
Each DiffNode may be edited according to its DiffType and represents a source code element according to its NodeType.
DiffNode's store parent and child information to build a graph.- Author:
- Paul Bittner, Sören Viegener, Benjamin Moosherr
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static classDiffNode.TimeDependentState<L extends Label>Bundles all the state that may be different before and after an edit. -
Field Summary
FieldsModifier and TypeFieldDescriptionThe diff type of this node, which determines if this node represents an inserted, removed, or unchanged element in a diff.private org.prop4j.Nodeprivate DiffLineNumberfinal VariationLabel<L> The label together with the node type of this node, which determines the type of the represented element in the diff (e.g., mapping or artifact).private final DiffNode.TimeDependentState<L> private final DiffNode.TimeDependentState<L> private DiffLineNumber -
Constructor Summary
ConstructorsConstructorDescriptionDiffNode(DiffType diffType, DiffLineNumber fromLines, DiffLineNumber toLines, org.prop4j.Node featureMapping, VariationLabel<L> label) Creates a DiffNode with the given parameters.DiffNode(DiffType diffType, NodeType nodeType, DiffLineNumber fromLines, DiffLineNumber toLines, org.prop4j.Node featureMapping, L label) Creates a DiffNode with the given parameters. -
Method Summary
Modifier and TypeMethodDescriptionvoidAdds this subtree below the given parents.voidThe same asinsertChild(org.variantsync.diffdetective.variation.diff.DiffNode<L>, int, org.variantsync.diffdetective.variation.diff.Time)but puts the node at the end of the children list instead of inserting it at a specific index.voidaddChildren(Collection<DiffNode<L>> children, Time time) Adds all given nodes at the timetimeas children usingaddChild(org.variantsync.diffdetective.variation.diff.DiffNode<L>, org.variantsync.diffdetective.variation.diff.Time).voidChecks that the VariationDiff is in a valid state.private DiffNode.TimeDependentState<L> booleanReturns true iff the path's in parent direction following the before parent and after parent are the very same.static DiffNode<DiffLinesLabel> createArtifact(DiffType diffType, DiffLineNumber fromLines, DiffLineNumber toLines, String code) Creates an artifact node with the given parameters.createArtifact(DiffType diffType, DiffLineNumber fromLines, DiffLineNumber toLines, L label) The same ascreateArtifact(DiffType, DiffLineNumber, DiffLineNumber, String)but with a generic label.createRoot(L label) Creates a new root node.deepCopy()voiddrop()Removes this subtree from its parents.voidRemoves this subtree from its parents at the timetime.static DiffNode<DiffLinesLabel> Reconstructs a node from the given id and sets the given label.Returns an efficient iterable representation of all direct children without duplicates.Returns a new set with all children of this node without duplicates.Returns an efficient stream representation of all direct children without duplicates.intgetChangeAmount(Time time) Gets the amount of nodes on the path from the root to this node which only exist at the timetime.getChildOrder(Time time) Returns the order of the children attime.intGets the length of the path from the root to this node at the timetime.Returns the diff type of this node.org.prop4j.NodegetFeatureMapping(Time time) Returns the full feature mapping formula of this node.org.prop4j.NodeReturns the formula that is stored in this node.Returns the starting line number of this node's corresponding text block.intgetID()Gets the firstifnode in the path from the root to this node at the timetime.getLabel()Returns the lines in the diff that are represented by this DiffNode as a single text.getLinesAtTime(Time time) Returns the range of line numbers of this node's corresponding source code before or after the edit.Returns the range of line numbers of this node's corresponding source code in the text-based diff.Returns the type of this node.Returns the parent of this node before or after the edit.org.prop4j.NodegetPresenceCondition(Time time) Returns the presence condition of this node before or after the edit.Returns the end line number of this node's corresponding text block.intReturns the number of unique child nodes.intindexOfChild(DiffNode<L> child, Time time) Returns the index of the given child in the list of children of this node.voidinsertChild(DiffNode<L> child, int index, Time time) Insertchildas child at the timetimeat the positionindex.booleanisAdd()Returns true iff this node represents an inserted element.booleanReturns true iff this node is the before or after parent of the given node.booleanReturns true iff this node is the parent of the given node at the given time.booleanisLeaf()Returns true iff this node has no children.booleanisNon()Returns true iff this node represents an unchanged element.booleanisRem()Returns true iff this node represents a removed element.booleanisRoot()Returns true if this node is a root node (has no parents).booleanReturns true if this subtree is exactly equal toother.private static <L extends Label>
booleanbooleanisSameAsIgnoringLineNumbers(DiffNode<L> other) Returns true if this subtree is exactly equal tootherexcept for line numbers and other metadata in labels.private static <L extends Label>
booleanisSameAsIgnoringLineNumbers(DiffNode<L> a, DiffNode<L> b, Set<DiffNode<L>> visited) voidMergesotherinto this node.voidTurns this node into a node withDiffTypeDiffType.NON.projection(Time time) Returns a view of thisDiffNodeas a variation node at the timetime.voidremoveChild(DiffNode<L> child, Time time) Removes the given node from this node's children before or after the edit.voidremoveChildren(Collection<DiffNode<L>> childrenToRemove) Removes all given children for all times.removeChildren(Time time) Removes all children before or after the edit.voidReplaces a child of this node with another node.voidsetFormula(org.prop4j.Node featureMapping) voidsetFromLine(DiffLineNumber from) voidSets the lines in the diff that are represented by this DiffNode to the given code.voidsetLinesAtTime(LineRange lineRange, Time time) Returns the range of line numbers of this node's corresponding source code before or after the edit.voidSplits anunmodifiednode into a removed and an added node.voidstealChildrenOf(DiffNode<L> other) Removes all children from the given node and adds them as children to this node (at all times).voidstealChildrenOf(Time time, DiffNode<L> other) Removes all children from the given node and adds them as children to this node at the given time.toString()static <T extends VariationNode<T,L1>, L1 extends Label, L2 extends Label>
DiffNode<L2> unchanged(Function<? super T, DiffNode<L2>> convert, VariationNode<T, L1> variationNode) Transforms aVariationNodeinto aDiffNodeby diffingvariationNodeto itself.static <T extends VariationNode<T,L>, L extends Label>
DiffNode<L> unchanged(VariationNode<T, L> variationNode) Transforms aVariationNodeinto aDiffNodeby diffingvariationNodeto itself.static <T extends VariationNode<T,L>, L extends Label>
DiffNode<L> unchangedFlat(VariationNode<T, L> variationNode) Transforms aVariationNodeinto aDiffNodeby diffingvariationNodeto itself.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitMethods inherited from interface org.variantsync.diffdetective.variation.tree.HasNodeType
isAnnotation, isArtifact, isConditionalAnnotation, isElif, isElse, isIf
-
Field Details
-
diffType
The diff type of this node, which determines if this node represents an inserted, removed, or unchanged element in a diff. -
label
The label together with the node type of this node, which determines the type of the represented element in the diff (e.g., mapping or artifact). -
from
-
to
-
featureMapping
private org.prop4j.Node featureMapping -
stateBefore
-
stateAfter
-
-
Constructor Details
-
DiffNode
public DiffNode(DiffType diffType, NodeType nodeType, DiffLineNumber fromLines, DiffLineNumber toLines, org.prop4j.Node featureMapping, L label) Creates a DiffNode with the given parameters.- Parameters:
diffType- The type of change made to this node.nodeType- The type of this node (i.e., mapping or artifact).fromLines- The starting line number of the corresponding text.toLines- The ending line number of the corresponding text.featureMapping- The formula stored in this node. Should be null for artifact nodes.label- The label of this node.
-
DiffNode
public DiffNode(DiffType diffType, DiffLineNumber fromLines, DiffLineNumber toLines, org.prop4j.Node featureMapping, VariationLabel<L> label) Creates a DiffNode with the given parameters.- Parameters:
diffType- The type of change made to this node.fromLines- The starting line number of the corresponding text.toLines- The ending line number of the corresponding text.featureMapping- The formula stored in this node. Should be null for artifact nodes.label- The label and type of this node.
-
-
Method Details
-
at
-
createRoot
Creates a new root node. The root is a neutral annotation (i.e., its feature mapping is "true"). -
createArtifact
public static DiffNode<DiffLinesLabel> createArtifact(DiffType diffType, DiffLineNumber fromLines, DiffLineNumber toLines, String code) Creates an artifact node with the given parameters. For parameter descriptions, seeDiffNode(DiffType, NodeType, DiffLineNumber, DiffLineNumber, Node, L). Thecodeparameter will be set as the node's label by splitting it into lines. -
createArtifact
public static <L extends Label> DiffNode<L> createArtifact(DiffType diffType, DiffLineNumber fromLines, DiffLineNumber toLines, L label) The same ascreateArtifact(DiffType, DiffLineNumber, DiffLineNumber, String)but with a generic label. -
getLabel
Returns the lines in the diff that are represented by this DiffNode as a single text. -
setLabel
Sets the lines in the diff that are represented by this DiffNode to the given code. Lines are identified by linebreak characters. -
getIfNode
Gets the firstifnode in the path from the root to this node at the timetime.- Returns:
- The first
ifnode in the path to the root at the timetime
-
getDepth
Gets the length of the path from the root to this node at the timetime.- Returns:
- the depth of the this node in the diff tree at the time
time
-
beforePathEqualsAfterPath
public boolean beforePathEqualsAfterPath()Returns true iff the path's in parent direction following the before parent and after parent are the very same. -
getTotalNumberOfChildren
public int getTotalNumberOfChildren()Returns the number of unique child nodes. -
getChangeAmount
Gets the amount of nodes on the path from the root to this node which only exist at the timetime. -
addBelow
Adds this subtree below the given parents. Inverse of drop.- Parameters:
newBeforeParent- Node that should be this node's before parent. May be null.newAfterParent- Node that should be this node's after parent. May be null.
-
drop
public void drop()Removes this subtree from its parents. Inverse of addBelow. -
drop
Removes this subtree from its parents at the timetime. -
indexOfChild
Returns the index of the given child in the list of children of this node. Returns -1 if the given node is not a child of this node. -
insertChild
Insertchildas child at the timetimeat the positionindex. -
addChild
The same asinsertChild(org.variantsync.diffdetective.variation.diff.DiffNode<L>, int, org.variantsync.diffdetective.variation.diff.Time)but puts the node at the end of the children list instead of inserting it at a specific index. -
addChildren
Adds all given nodes at the timetimeas children usingaddChild(org.variantsync.diffdetective.variation.diff.DiffNode<L>, org.variantsync.diffdetective.variation.diff.Time).- Parameters:
children- Nodes to add as children.time- whether to addchildrenbefore or after the edit
-
removeChild
Removes the given node from this node's children before or after the edit. The node might still remain a child after or before the edit.- Parameters:
child- the child to removetime- whetherchildshould be removed before or after the edit
-
removeChildren
Removes all given children for all times. None of the given nodes will be a child, neither before nor after the edit, afterwards.- Parameters:
childrenToRemove- Nodes that should not be children of this node anymore.
-
removeChildren
Removes all children before or after the edit. Afterwards, this node will have no children at the given time.- Parameters:
time- whether to remove all children before or after the edit- Returns:
- All removed children.
-
stealChildrenOf
Removes all children from the given node and adds them as children to this node at the given time. The given node will have no children afterwards at the given time.- Parameters:
other- The node whose children should be stolen for the given time.
-
stealChildrenOf
Removes all children from the given node and adds them as children to this node (at all times). The given node will have no children afterwards.- Parameters:
other- The node whose children should be stolen.
-
split
Splits anunmodifiednode into a removed and an added node. Only one new node is created. Depending ontime,thisis changed intoDiffType.ADDforTime.BEFOREorDiffType.REMforTime.AFTER.- Parameters:
time- decides which node is created- Returns:
- the new node that exists at time
time.
-
join
Mergesotherinto this node.otheris removed from the graph and this node inherits all of its edges. This node andotherneed to be compatible (exist at different times and have the samenode typeand compatiblelabels).Both
thisandothermust not bethe root.- Parameters:
other- the node which is removed from the graph
-
replaceChild
Replaces a child of this node with another node.If
oldChildis not a child of this node, nothing happens.- Parameters:
oldChild- the child that is removednewChild- the child that is insertedtime- at which the child relation is changed
-
getParent
Returns the parent of this node before or after the edit. -
getFromLine
Returns the starting line number of this node's corresponding text block. -
setFromLine
-
getToLine
Returns the end line number of this node's corresponding text block. The line number is exclusive (i.e., it points 1 behind the last included line). -
setToLine
-
getLinesInDiff
Returns the range of line numbers of this node's corresponding source code in the text-based diff.- See Also:
-
getLinesAtTime
Returns the range of line numbers of this node's corresponding source code before or after the edit. -
setLinesAtTime
Returns the range of line numbers of this node's corresponding source code before or after the edit. -
getFormula
public org.prop4j.Node getFormula()Returns the formula that is stored in this node. The formula is null for artifact nodes (i.e.,NodeType.ARTIFACT). The formula is not null for mapping nodes- See Also:
-
setFormula
public void setFormula(org.prop4j.Node featureMapping) -
getChildOrder
Returns the order of the children attime. -
getAllChildrenStream
Returns an efficient stream representation of all direct children without duplicates. In particular, children which are both before and after children of this node are only contained once. The order of the children is unspecified. -
getAllChildren
Returns an efficient iterable representation of all direct children without duplicates. Note: The returned iterable can only be traversed once.- See Also:
-
getAllChildrenSet
Returns a new set with all children of this node without duplicates.- See Also:
-
getFeatureMapping
Returns the full feature mapping formula of this node. The feature mapping of anNodeType.IFnode is itsdirect feature mapping. The feature mapping ofNodeType.ELSEandNodeType.ELIFnodes is determined by all formulas in the respective if-elif-else chain. The feature mapping of anartifactnode is the feature mapping of its parent. See Equation (1) in our paper (+ its extension to time for variation tree diffs described in Section 3.1).- Parameters:
time- Whether to return the feature mapping clauses before or after the edit.- Returns:
- The feature mapping of this node for the given parent edges.
-
getPresenceCondition
Returns the presence condition of this node before or after the edit. See Equation (2) in our paper (+ its extension to time for variation tree diffs described in Section 3.1).- Parameters:
time- Whether to return the presence condition before or after the edit.- Returns:
- The presence condition of this node for the given parent edges.
-
isChild
Returns true iff this node is the before or after parent of the given node. -
isChild
Returns true iff this node is the parent of the given node at the given time. -
isLeaf
public boolean isLeaf()Returns true iff this node has no children. -
isRem
public boolean isRem()Returns true iff this node represents a removed element.- See Also:
-
isNon
public boolean isNon()Returns true iff this node represents an unchanged element.- See Also:
-
isAdd
public boolean isAdd()Returns true iff this node represents an inserted element.- See Also:
-
getDiffType
Returns the diff type of this node. -
getNodeType
Description copied from interface:HasNodeTypeReturns the type of this node.- Specified by:
getNodeTypein interfaceHasNodeType
-
isRoot
public boolean isRoot()Returns true if this node is a root node (has no parents). -
getID
public int getID()- Returns:
- An integer that uniquely identifiers this DiffNode within its patch.
From the returned id a new node with all essential attributes reconstructed can be obtained
by using
fromID(int, java.lang.String). Note that only26bits of the line number are encoded, so if the line number is bigger than2^26, this id will no longer be unique.
-
fromID
Reconstructs a node from the given id and sets the given label. An id uniquely determines a node'sgetNodeType(),diffType, andline number in the diff. The almost-inverse function isgetID()but the conversion is not lossless.- Parameters:
id- The id from which to reconstruct the node.label- The label the node should have.- Returns:
- The reconstructed DiffNode.
-
assertConsistency
public void assertConsistency()Checks that the VariationDiff is in a valid state. In particular, this method checks that all edges are well-formed (e.g., edges can be inconsistent because edges are double-linked). This method also checks that a node with exactly one parent was edited, and that a node with exactly two parents was not edited. To check all children recursively, useVariationDiff.assertConsistency().- Throws:
AssertionError- when an inconsistency is detected.- See Also:
-
projection
Returns a view of thisDiffNodeas a variation node at the timetime.See the
projectfunction in section 3.1 of our paper. -
unchangedFlat
public static <T extends VariationNode<T,L>, DiffNode<L> unchangedFlatL extends Label> (VariationNode<T, L> variationNode) Transforms aVariationNodeinto aDiffNodeby diffingvariationNodeto itself. Acts on only the given node and does not perform recursive translations. -
unchanged
public static <T extends VariationNode<T,L1>, DiffNode<L2> unchangedL1 extends Label, L2 extends Label> (Function<? super T, DiffNode<L2>> convert, VariationNode<T, L1> variationNode) Transforms aVariationNodeinto aDiffNodeby diffingvariationNodeto itself. Recursively translates all children. This is the inverse ofprojection(org.variantsync.diffdetective.variation.diff.Time)iff the originalDiffNodewasn't modified (all node had adiff typeofDiffType.NON).- Parameters:
convert- A function to translate single nodes (without their hierarchy).
-
deepCopy
-
deepCopy
-
shallowCopy
-
makeUnchanged
public void makeUnchanged()Turns this node into a node withDiffTypeDiffType.NON. To retain consistency of the variation diff, this node will also ensure that this node will have a parent at all times. To this end, the parent of this node will also be made unchanged if necessary, potentially making some or all ancestors of this node unchanged recursively. This method has no effect when this node is already unchanged. -
unchanged
public static <T extends VariationNode<T,L>, DiffNode<L> unchangedL extends Label> (VariationNode<T, L> variationNode) Transforms aVariationNodeinto aDiffNodeby diffingvariationNodeto itself. Recursively translates all children. This is the inverse ofprojection(org.variantsync.diffdetective.variation.diff.Time)iff the originalDiffNodewasn't modified (all node had adiff typeofDiffType.NON). -
isSameAs
Returns true if this subtree is exactly equal toother. This check uses equality checks instead of identity. -
isSameAs
-
isSameAsIgnoringLineNumbers
Returns true if this subtree is exactly equal tootherexcept for line numbers and other metadata in labels. This equality is a weaker equality thanisSameAs(DiffNode)(i.e., whenever isSameAs returns true, so does isSameAsIgnoringLineNumbers). Labels of DiffNodes are compared viaLabel.observablyEqual(Label, Label). This check uses equality checks instead of identity. -
isSameAsIgnoringLineNumbers
-
toString
-