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
-
Field Summary
Modifier and TypeFieldDescriptionThe children before and after the edit.The diff type of this node, which determines if this node represents an inserted, removed, or unchanged element in a diff.private org.prop4j.Node
private DiffLineNumber
final 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).The parentsDiffNode
before and after the edit.private Projection<L>[]
Cache for before and after projections.private DiffLineNumber
-
Constructor Summary
ConstructorDescriptionDiffNode
(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 TypeMethodDescriptionvoid
Adds this subtree below the given parents.void
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.void
addChildren
(Collection<DiffNode<L>> children, Time time) Adds all given nodes at the timetime
as children usingaddChild(org.variantsync.diffdetective.variation.diff.DiffNode<L>, org.variantsync.diffdetective.variation.diff.Time)
.void
Checks that the VariationDiff is in a valid state.boolean
Returns 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()
void
drop()
Removes this subtree from its parents.void
Removes 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.int
getChangeAmount
(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
.int
Gets the length of the path from the root to this node at the timetime
.Returns the diff type of this node.org.prop4j.Node
getFeatureMapping
(Time time) Returns the full feature mapping formula of this node.org.prop4j.Node
Returns the formula that is stored in this node.Returns the starting line number of this node's corresponding text block.int
getID()
Gets the firstif
node 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.Node
getPresenceCondition
(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.int
Returns the number of unique child nodes.int
indexOfChild
(DiffNode<L> child, Time time) Returns the index of the given child in the list of children of this node.void
insertChild
(DiffNode<L> child, int index, Time time) Insertchild
as child at the timetime
at the positionindex
.boolean
isAdd()
Returns true iff this node represents an inserted element.boolean
Returns true iff this node is the before or after parent of the given node.boolean
Returns true iff this node is the parent of the given node at the given time.boolean
isLeaf()
Returns true iff this node has no children.boolean
isNon()
Returns true iff this node represents an unchanged element.boolean
isRem()
Returns true iff this node represents a removed element.boolean
isRoot()
Returns true if this node is a root node (has no parents).boolean
Returns true if this subtree is exactly equal toother
.private static <L extends Label>
booleanprojection
(Time time) Returns a view of thisDiffNode
as a variation node at the timetime
.void
removeChild
(DiffNode<L> child, Time time) Removes the given node from this node's children before or after the edit.void
removeChildren
(Collection<DiffNode<L>> childrenToRemove) Removes all given children for all times.removeChildren
(Time time) Removes all children before or after the edit.void
setFormula
(org.prop4j.Node featureMapping) void
setFromLine
(DiffLineNumber from) void
Sets the lines in the diff that are represented by this DiffNode to the given code.void
setLinesAtTime
(LineRange lineRange, Time time) Returns the range of line numbers of this node's corresponding source code before or after the edit.void
void
stealChildrenOf
(DiffNode<L> other) Removes all children from the given node and adds them as children to this node at the respective times.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 aVariationNode
into aDiffNode
by diffingvariationNode
to itself.static <T extends VariationNode<T,
L>, L extends Label>
DiffNode<L>unchanged
(VariationNode<T, L> variationNode) Transforms aVariationNode
into aDiffNode
by diffingvariationNode
to itself.static <T extends VariationNode<T,
L>, L extends Label>
DiffNode<L>unchangedFlat
(VariationNode<T, L> variationNode) Transforms aVariationNode
into aDiffNode
by diffingvariationNode
to itself.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
Methods 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 -
parents
The parentsDiffNode
before and after the edit. This array has to be indexed byTime.ordinal()
Invariant: IffgetParent(time) != null
thengetParent(time).getChildOrder(time).contains(this)
. -
children
The children before and after the edit. This array has to be indexed byTime.ordinal()
Invariant: IffgetChildOrder(time).contains(child)
thenchild.getParent(time) == this
. -
projections
Cache for before and after projections. It stores the projection node at each time so that only one instance ofProjection
perTime
is ever created. This array has to be indexed byTime.ordinal()
This field is required to allow identity tests of
Projection
s with==
.
-
-
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.
-
-
Method Details
-
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)
. Thecode
parameter 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 firstif
node in the path from the root to this node at the timetime
.- Returns:
- The first
if
node 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
Insertchild
as child at the timetime
at 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 timetime
as 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 addchildren
before 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
- whetherchild
should 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 respective times. The order of children is not stable because first all before children are transferred and then all after children. The given node will have no children afterwards.- Parameters:
other
- The node whose children should be stolen.
-
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. -
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.IF
node is itsdirect feature mapping
. The feature mapping ofNodeType.ELSE
andNodeType.ELIF
nodes is determined by all formulas in the respective if-elif-else chain. The feature mapping of anartifact
node 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:HasNodeType
Returns the type of this node.- Specified by:
getNodeType
in 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 only26
bits 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.- Throws:
AssertionError
- when an inconsistency is detected.- See Also:
-
projection
Returns a view of thisDiffNode
as a variation node at the timetime
.See the
project
function 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 aVariationNode
into aDiffNode
by diffingvariationNode
to 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 aVariationNode
into aDiffNode
by diffingvariationNode
to itself. Recursively translates all children. This is the inverse ofprojection(org.variantsync.diffdetective.variation.diff.Time)
iff the originalDiffNode
wasn't modified (all node had adiff type
ofDiffType.NON
).- Parameters:
convert
- A function to translate single nodes (without their hierarchy).
-
deepCopy
-
deepCopy
-
shallowCopy
-
unchanged
public static <T extends VariationNode<T,L>, DiffNode<L> unchangedL extends Label> (VariationNode<T, L> variationNode) Transforms aVariationNode
into aDiffNode
by diffingvariationNode
to itself. Recursively translates all children. This is the inverse ofprojection(org.variantsync.diffdetective.variation.diff.Time)
iff the originalDiffNode
wasn't modified (all node had adiff type
ofDiffType.NON
). -
isSameAs
Returns true if this subtree is exactly equal toother
. This check uses equality checks instead of identity. -
isSameAs
-
toString
-