Skip to content

Commit

Permalink
Add NodeHistoryAccumulator utility class
Browse files Browse the repository at this point in the history
Merge branch 'hurthwell-refactor-2' into 'master'

See merge request persper/code-analytics!70
  • Loading branch information
hezyin committed May 8, 2019
2 parents 11781f3 + e5ca9d3 commit b992df4
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
1 change: 1 addition & 0 deletions persper/analytics2/abstractions/callcommitgraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ def update_node_history(self, node_id: NodeId, commit_hexsha: str, added_lines:
If commit_hexsha doesn't exist in history, add the entry to history.
If commit_hexsha exists in history, the entry will be *replaced*.
Note the entire node history entry of this hexsha will be replaced rather than merged.
To accumulate multiple modifications to a node in the same commit, use `NodeHistoryAccumulator` helper class.
"""
pass

Expand Down
62 changes: 62 additions & 0 deletions persper/analytics2/utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from persper.analytics2.abstractions.callcommitgraph import IWriteOnlyCallCommitGraph, NodeId


class NodeHistoryAccumulator():
"""
Provides convenient methods for accumulating node history.
(i.e. the added/removed lines to the same node in a single commit)
"""

def __init__(self):
# [NodeId]: [added_lines, removed_lines]
self._nodes = {}

def clear(self):
"""
Clears all the accumulated histroy information contained in this instance.
"""
self._nodes.clear()

def add(self, node_id: NodeId, added_lines: int = 0, removed_lines: int = 0):
"""
Accumulates the added/removed lines of code to the specific node_id.
"""
info = self._nodes.get(node_id, None)
if info == None:
if not isinstance(node_id, NodeId):
raise ValueError("node_id should be NodeId.")
if not isinstance(added_lines, int):
raise ValueError("added_lines should be int.")
if not isinstance(removed_lines, int):
raise ValueError("removed_lines should be int.")
if added_lines != 0 or removed_lines != 0:
info = [added_lines, removed_lines]
self._nodes[node_id] = info
else:
info[0] += added_lines
info[1] += removed_lines

def get(self, node_id: NodeId):
"""
Gets the accumulated added/removed lines of code for the specified node ID.
returns
(added_lines: int, removed_lines: int)
"""
info = self._nodes.get(node_id, None)
if info == None:
if not isinstance(node_id, NodeId):
raise ValueError("node_id should be NodeId.")
return 0, 0
return info[0], info[1]

def apply(self, graph: IWriteOnlyCallCommitGraph, commit_hexsha: str):
"""
Applies the node history contained in this instance to the specified call commit graph.
params
graph: the call commit graph to be updated.
commit_hexsha: When updating the call commit graph, specify the current commit hexsha.
remarks
You may want to call `clear` to reset the change history after calling this method.
"""
for id, (added, removed) in self._nodes:
graph.update_node_history(id, commit_hexsha, added, removed)
20 changes: 20 additions & 0 deletions test/analytics2/utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from persper.analytics2.utilities import NodeHistoryAccumulator
from persper.analytics2.abstractions.callcommitgraph import NodeId


def test_node_history_accumulator():
nodeHistory = NodeHistoryAccumulator()
testId0 = NodeId("CTest0", "cpp")
testId1 = NodeId("CTest1", "cpp")
testId2 = NodeId("CTest2", "cpp")
nodeHistory.add(testId1, 10, 20)
nodeHistory.add(testId2, -10, 20)
nodeHistory.add(testId1, 5, -5)
assert nodeHistory.get(testId0) == (0, 0)
assert nodeHistory.get(testId1) == (15, 15)
assert nodeHistory.get(testId2) == (-10, 20)
# TODO test `apply` with MemoryCCG
nodeHistory.clear()
assert nodeHistory.get(testId0) == (0, 0)
assert nodeHistory.get(testId1) == (0, 0)
assert nodeHistory.get(testId2) == (0, 0)

0 comments on commit b992df4

Please sign in to comment.