diff --git a/persper/analytics/analyzer2.py b/persper/analytics/analyzer2.py index c07290c4d75..c670ed74bd5 100644 --- a/persper/analytics/analyzer2.py +++ b/persper/analytics/analyzer2.py @@ -1,13 +1,13 @@ import asyncio -from abc import ABC import collections.abc -from typing import Union, Set, Optional, List +from abc import ABC +from typing import List, Optional, Set, Union from git import Commit, Diff, DiffIndex, Repo -from persper.analytics.git_tools import (diff_with_commit, get_contents) -from persper.analytics.graph_server import CommitSeekingMode, GraphServer from persper.analytics.commit_classifier import CommitClassifier +from persper.analytics.git_tools import diff_with_commit, get_contents +from persper.analytics.graph_server import CommitSeekingMode, GraphServer from persper.analytics.score import commit_overall_scores @@ -44,6 +44,10 @@ def __setstate__(self, state): self.terminalCommit = state["_terminalCommit"] self._s_visitedCommits = _ReadOnlySet(self._visitedCommits) + @property + def graphServer(self): + return self._graphServer + @property def observer(self): """ @@ -155,6 +159,7 @@ def printCommitStatus(status: str): # then go on with current commit printCommitStatus("Going forward.") await self._analyzeCommit(commit, parent, CommitSeekingMode.NormalForward) + self._visitedCommits.add(commit.hexsha) graphServerLastCommit = commit.hexsha analyzedCommits += 1 diff --git a/persper/analytics/call_commit_graph.py b/persper/analytics/call_commit_graph.py index f99ff124554..6d3db3bb0f1 100644 --- a/persper/analytics/call_commit_graph.py +++ b/persper/analytics/call_commit_graph.py @@ -7,6 +7,7 @@ from networkx.readwrite import json_graph from persper.analytics.devrank import devrank from persper.analytics.score import normalize +from typing import Union, Set, List, Dict, Optional class CommitIdGenerators: @@ -29,14 +30,23 @@ class CallCommitGraph: and edit histories across commits. """ - def __init__(self, node_link_data=None, commit_id_generator=CommitIdGenerators.fromHexsha): - if node_link_data: - self._digraph = json_graph.node_link_graph(node_link_data) + def __init__(self, graph_data: Optional[Dict] = None, commit_id_generator=CommitIdGenerators.fromHexsha): + if graph_data: + self._digraph = json_graph.node_link_graph( + CallCommitGraph._to_networkx_format(graph_data)) else: self._digraph = self._new_graph() self._commit_id_generator = commit_id_generator self._current_commit_id = None + @staticmethod + def _to_networkx_format(graph_data: Dict) -> Dict: + graph_data['multigraph'] = False + graph_data['directed'] = True + for node in graph_data['nodes']: + node['files'] = set(node['files']) + return graph_data + def reset(self): """Reset all internal states""" self._digraph = self._new_graph() @@ -59,6 +69,10 @@ def commits(self): # https://networkx.github.io/documentation/stable/tutorial.html#graph-attributes return self._digraph.graph['commits'] + def files(self, node: str) -> Set[str]: + """Provide read-only access to `files` attribute of a node""" + return self.nodes()[node]['files'] + def __contains__(self, node): """Implement membership check""" return node in self._digraph @@ -82,8 +96,8 @@ def _next_cindex(self): return self._cur_cindex() + 1 # TODO: remove the default value of files - def add_node(self, node, files=[]): - self._digraph.add_node(node, size=None, history={}, files=files) + def add_node(self, node: str, files: Union[Set[str], List[str]] = []): + self._digraph.add_node(node, size=None, history={}, files=set(files)) # add_node must be called on source and target first def add_edge(self, source, target): @@ -106,11 +120,11 @@ def update_node_history(self, node, num_adds, num_dels): node_history[self._current_commit_id] = {'adds': num_adds, 'dels': num_dels} # read/write access to node history are thourgh this function - def _get_node_history(self, node): + def _get_node_history(self, node: str) -> Dict[str, Dict[str, int]]: return self._digraph.nodes[node]['history'] - def update_node_files(self, node, new_files): - self._digraph.nodes[node]['files'] = new_files + def update_node_files(self, node: str, new_files: Union[Set[str], List[str]]): + self._digraph.nodes[node]['files'] = set(new_files) # TODO: provide other options for computing a node's size def _set_all_nodes_size(self, black_set=None): diff --git a/persper/analytics/call_graph/c.py b/persper/analytics/call_graph/c.py index 961f147d755..18d84449ede 100644 --- a/persper/analytics/call_graph/c.py +++ b/persper/analytics/call_graph/c.py @@ -1,4 +1,5 @@ from persper.analytics.call_graph.utils import ns, line_attr +from typing import Set class NotFunctionCallError(Exception): @@ -83,9 +84,10 @@ def update_graph(ccgraph, ast_list, change_stats): if caller_name not in ccgraph: ccgraph.add_node(caller_name, [filename]) else: - files = ccgraph.nodes()[caller_name]['files'] + files: Set[str] = ccgraph.files(caller_name) if filename not in files: - ccgraph.update_node_files(caller_name, files + [filename]) + files.add(filename) + ccgraph.update_node_files(caller_name, files) for call in function.xpath('.//srcml:call', namespaces=ns): try: diff --git a/persper/analytics/go.py b/persper/analytics/go.py index 284ab5cf6d0..e4a39fb178d 100644 --- a/persper/analytics/go.py +++ b/persper/analytics/go.py @@ -40,10 +40,7 @@ def update_graph(self, old_filename, old_src, def get_graph(self): graph_url = self.server_addr + '/callgraph' r = requests.get(graph_url) - graph_data = r.json() - graph_data['directed'] = True - graph_data['multigraph'] = False - return CallCommitGraph(graph_data) + return CallCommitGraph(graph_data=r.json()) def reset_graph(self): reset_url = urllib.parse.urljoin(self.server_addr, '/reset') diff --git a/persper/analytics/lsp_graph_server/callgraph/builder.py b/persper/analytics/lsp_graph_server/callgraph/builder.py index b54bd46bec6..37923c2aeb3 100644 --- a/persper/analytics/lsp_graph_server/callgraph/builder.py +++ b/persper/analytics/lsp_graph_server/callgraph/builder.py @@ -58,7 +58,7 @@ def PopulateSymbols(symbols): if filterResult == None: continue if filterResult == False: - if isinstance(s, SymbolInformation): + if isinstance(s, DocumentSymbol): PopulateSymbols(s.children) continue if isinstance(s, DocumentSymbol): @@ -66,12 +66,12 @@ def PopulateSymbols(symbols): symbolKinds[s.selectionRange.start.toTuple()] = s.kind self._scopes.append(CallGraphScope(s.detail or s.name, s.kind, fileName, s.range.start, s.range.end)) + if s.children: + PopulateSymbols(s.children) elif isinstance(s, SymbolInformation): symbolKinds[(s.location.range.start.line, s.name)] = (s.location.range.start.character, s.kind) self._scopes.append(CallGraphScope(s.containerName, s.kind, fileName, s.location.range.start, s.location.range.end)) - if s.children: - PopulateSymbols(s.children) else: _logger.error("Invalid DocumentSymbol in %s: %s", fileName, s) @@ -293,6 +293,11 @@ def filterSymbol(self, symbol: Union[DocumentSymbol, SymbolInformation]) -> bool False symbol should be excluded, while its children will pass filterSymbol None symbol and its children will be excluded """ + if symbol.kind in { + SymbolKind.Parameter, + SymbolKind.TypeParameter + }: + return None return symbol.kind in { SymbolKind.Constructor, SymbolKind.Enum, diff --git a/persper/analytics/lsp_graph_server/callgraph/manager.py b/persper/analytics/lsp_graph_server/callgraph/manager.py index b4b51a0296a..85b6cd6d00b 100644 --- a/persper/analytics/lsp_graph_server/callgraph/manager.py +++ b/persper/analytics/lsp_graph_server/callgraph/manager.py @@ -42,6 +42,7 @@ async def buildGraph(self, fileNames: Union[str, Iterable[str]] = None, globPatt branchCounter = 0 # with dups fileCounter = 0 await self._builder.waitForFileSystem() + def pushBranch(branch): nonlocal branchCounter try: @@ -64,7 +65,7 @@ def pushBranch(branch): pushBranch(b) if globPattern or not fileNames: async for b in self._builder.buildCallGraphInFiles(globPattern): - pushBranch(b) + pushBranch(b) if fileNames and not globPattern: _logger.info("Added %d branches from %d files.", branchCounter, fileCounter) else: diff --git a/persper/analytics/lsp_graph_server/languageclient/lspcontract.py b/persper/analytics/lsp_graph_server/languageclient/lspcontract.py index 930e3741e03..390f0f0da42 100644 --- a/persper/analytics/lsp_graph_server/languageclient/lspcontract.py +++ b/persper/analytics/lsp_graph_server/languageclient/lspcontract.py @@ -237,7 +237,7 @@ def getSymbolRange(self): return self.selectionRange def __str__(self): - return self.name + "[" + self.kind + "]" + return str.format("{0}({1}){2}", self.name, self.kind, self.children or "") def toDict(self): raise NotImplementedError() diff --git a/test/test_analytics/baseline/cpp_test_repo/A.g.json b/test/test_analytics/baseline/cpp_test_repo/A.g.json index 3a503bd6209..2594c7d3aa5 100644 --- a/test/test_analytics/baseline/cpp_test_repo/A.g.json +++ b/test/test_analytics/baseline/cpp_test_repo/A.g.json @@ -1,5 +1,9 @@ { "edges": { + "ArgumentException::ArgumentException(const std::string &message, const std::string &argumentName)|->|static std::string ArgumentException::BuildMessage(const std::string &message, const std::string &argumentName)": { + "addedBy": "A", + "weight": null + }, "ConfigurationParser::ConfigurationParser(std::filesystem::path filePath)|->|TStream OpenAndValidate(const TPath arg1)": { "addedBy": "A", "weight": null @@ -28,30 +32,10 @@ "addedBy": "A", "weight": null }, - "bool Confirm(const std::string &prompt)|->|bool Confirm(const std::string &prompt)": { - "addedBy": "A", - "weight": null - }, - "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)|->|bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)": { - "addedBy": "A", - "weight": null - }, "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)|->|enum class StringComparison : int {}": { "addedBy": "A", "weight": null }, - "const char *FriendlyNameOf(const ReliabilityNetworkEntry &instance)|->|const char *FriendlyNameOf()": { - "addedBy": "A", - "weight": null - }, - "const char *FriendlyNameOf(const std::type_index &type)|->|const char *FriendlyNameOf()": { - "addedBy": "A", - "weight": null - }, - "const char *FriendlyNameOf(const type_info &type)|->|const char *FriendlyNameOf()": { - "addedBy": "A", - "weight": null - }, "int main(int argc, char *argv[])|->|TStream OpenAndValidate(const TPath arg1)": { "addedBy": "A", "weight": null @@ -59,10 +43,6 @@ "int main(int argc, char *argv[])|->|bool ConfigurationParser::GetBool(const std::string &key, bool defaultValue) const": { "addedBy": "A", "weight": null - }, - "void ReportException(const std::exception &ex, int level)|->|void ReportException(const std::exception &ex, int level)": { - "addedBy": "A", - "weight": null } }, "nodes": { @@ -162,6 +142,66 @@ }, "size": null }, + "ArgumentException::ArgumentException(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 2, + "dels": 0 + } + }, + "size": null + }, + "ArgumentException::ArgumentException(const std::string &message, const std::string &argumentName)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 2, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler &BlockExitHandler::operator=(const BlockExitHandler &) = delete": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler::BlockExitHandler(const BlockExitHandler &) = delete": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler::~BlockExitHandler() noexcept": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 11, + "dels": 0 + } + }, + "size": null + }, "ConfigurationParser::ConfigurationParser(std::filesystem::path filePath)": { "files": [ "TextFileParsers.cpp" @@ -186,14 +226,49 @@ }, "size": null }, + "Exception::Exception()": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "Exception::~Exception() noexcept": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "InvalidCastException::InvalidCastException(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "RowReader &operator>>(RowReader &reader, bool &rhs)": { "files": [ - "TextFileParsers.cpp", - "TextFileParsers.h" + "TextFileParsers.cpp" ], "history": { "A": { - "adds": 25, + "adds": 24, "dels": 0 } }, @@ -201,12 +276,11 @@ }, "RowReader &operator>>(RowReader &reader, double &rhs)": { "files": [ - "TextFileParsers.cpp", - "TextFileParsers.h" + "TextFileParsers.cpp" ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -214,12 +288,11 @@ }, "RowReader &operator>>(RowReader &reader, float &rhs)": { "files": [ - "TextFileParsers.cpp", - "TextFileParsers.h" + "TextFileParsers.cpp" ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -227,12 +300,11 @@ }, "RowReader &operator>>(RowReader &reader, int &rhs)": { "files": [ - "TextFileParsers.cpp", - "TextFileParsers.h" + "TextFileParsers.cpp" ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -240,12 +312,11 @@ }, "RowReader &operator>>(RowReader &reader, long &rhs)": { "files": [ - "TextFileParsers.cpp", - "TextFileParsers.h" + "TextFileParsers.cpp" ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -253,12 +324,23 @@ }, "RowReader &operator>>(RowReader &reader, std::string &rhs)": { "files": [ - "TextFileParsers.cpp", + "TextFileParsers.cpp" + ], + "history": { + "A": { + "adds": 16, + "dels": 0 + } + }, + "size": null + }, + "RowReader::operator bool() const": { + "files": [ "TextFileParsers.h" ], "history": { "A": { - "adds": 17, + "adds": 4, "dels": 0 } }, @@ -300,6 +382,30 @@ }, "size": null }, + "TIterator _RangeToEnumerable::begin()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "TIterator _RangeToEnumerable::end()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "TStream &operator>>(TStream &s, RowReader &reader)": { "files": [ "TextFileParsers.h" @@ -360,6 +466,18 @@ }, "size": null }, + "_RangeToEnumerable::_RangeToEnumerable(const std::pair range)": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "_RangeToEnumerable RangeToEnumerable(const std::pair range)": { "files": [ "Utility.h" @@ -398,12 +516,11 @@ }, "bool Confirm(const std::string &prompt)": { "files": [ - "Utility.cpp", - "Utility.h" + "Utility.cpp" ], "history": { "A": { - "adds": 18, + "adds": 17, "dels": 0 } }, @@ -411,12 +528,35 @@ }, "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)": { "files": [ - "Utility.cpp", + "Utility.cpp" + ], + "history": { + "A": { + "adds": 29, + "dels": 0 + } + }, + "size": null + }, + "bool RowReader::operator!() const": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "bool _RangeToEnumerable::empty()": { + "files": [ "Utility.h" ], "history": { "A": { - "adds": 30, + "adds": 1, "dels": 0 } }, @@ -446,9 +586,9 @@ }, "size": null }, - "const char *FriendlyNameOf()": { + "const char *Exception::what() const noexcept": { "files": [ - "Utility.h" + "Exceptions.h" ], "history": { "A": { @@ -458,7 +598,7 @@ }, "size": null }, - "const char *FriendlyNameOf(const ReliabilityNetworkEntry &instance)": { + "const char *FriendlyNameOf()": { "files": [ "Utility.h" ], @@ -470,9 +610,9 @@ }, "size": null }, - "const char *FriendlyNameOf(const std::type_index &type)": { + "const std::string &ArgumentException::ArgumentName() const": { "files": [ - "Utility.h" + "Exceptions.h" ], "history": { "A": { @@ -482,9 +622,9 @@ }, "size": null }, - "const char *FriendlyNameOf(const type_info &type)": { + "const std::stringstream &RowReader::LineStream() const": { "files": [ - "Utility.h" + "TextFileParsers.h" ], "history": { "A": { @@ -518,6 +658,54 @@ }, "size": null }, + "explicit BlockExitHandler::BlockExitHandler(const std::function &handler)": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "explicit Exception::Exception(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 6, + "dels": 0 + } + }, + "size": null + }, + "explicit OperationFailureException::OperationFailureException(int errorCode)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "explicit RowReader::RowReader(bool keepWhitespace, char delim)": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 3, + "dels": 0 + } + }, + "size": null + }, "inline std::string to_string(const std::pair &value)": { "files": [ "Utility.h" @@ -554,6 +742,30 @@ }, "size": null }, + "size_t RowReader::LineNumber() const": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "static std::string ArgumentException::BuildMessage(const std::string &message, const std::string &argumentName)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 5, + "dels": 0 + } + }, + "size": null + }, "std::shared_ptr safe_pointer_cast(const std::shared_ptr &obj)": { "files": [ "Utility.h" @@ -604,12 +816,23 @@ }, "void ReportException(const std::exception &ex, int level)": { "files": [ - "Utility.cpp", - "Utility.h" + "Utility.cpp" + ], + "history": { + "A": { + "adds": 20, + "dels": 0 + } + }, + "size": null + }, + "void RowReader::ResetLineNumber()": { + "files": [ + "TextFileParsers.h" ], "history": { "A": { - "adds": 21, + "adds": 1, "dels": 0 } }, diff --git a/test/test_analytics/baseline/cpp_test_repo/B.g.json b/test/test_analytics/baseline/cpp_test_repo/B.g.json index aebb4ca25f3..d0db7b42971 100644 --- a/test/test_analytics/baseline/cpp_test_repo/B.g.json +++ b/test/test_analytics/baseline/cpp_test_repo/B.g.json @@ -1,5 +1,9 @@ { "edges": { + "ArgumentException::ArgumentException(const std::string &message, const std::string &argumentName)|->|static std::string ArgumentException::BuildMessage(const std::string &message, const std::string &argumentName)": { + "addedBy": "A", + "weight": null + }, "ConfigurationParser::ConfigurationParser(std::filesystem::path filePath)|->|TStream OpenAndValidate(const TPath arg1)": { "addedBy": "A", "weight": null @@ -28,30 +32,10 @@ "addedBy": "A", "weight": null }, - "bool Confirm(const std::string &prompt)|->|bool Confirm(const std::string &prompt)": { - "addedBy": "B", - "weight": null - }, - "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)|->|bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)": { - "addedBy": "B", - "weight": null - }, "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)|->|enum class StringComparison : int {}": { "addedBy": "B", "weight": null }, - "const char *FriendlyNameOf(const ReliabilityNetworkEntry &instance)|->|const char *FriendlyNameOf()": { - "addedBy": "A", - "weight": null - }, - "const char *FriendlyNameOf(const std::type_index &type)|->|const char *FriendlyNameOf()": { - "addedBy": "A", - "weight": null - }, - "const char *FriendlyNameOf(const type_info &type)|->|const char *FriendlyNameOf()": { - "addedBy": "A", - "weight": null - }, "int main(int argc, char *argv[])|->|TStream OpenAndValidate(const TPath arg1)": { "addedBy": "B", "weight": null @@ -71,10 +55,6 @@ "int main(int argc, char *argv[])|->|void ReportException(const std::exception &ex, int level)": { "addedBy": "B", "weight": null - }, - "void ReportException(const std::exception &ex, int level)|->|void ReportException(const std::exception &ex, int level)": { - "addedBy": "B", - "weight": null } }, "nodes": { @@ -174,6 +154,66 @@ }, "size": null }, + "ArgumentException::ArgumentException(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 2, + "dels": 0 + } + }, + "size": null + }, + "ArgumentException::ArgumentException(const std::string &message, const std::string &argumentName)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 2, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler &BlockExitHandler::operator=(const BlockExitHandler &) = delete": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler::BlockExitHandler(const BlockExitHandler &) = delete": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler::~BlockExitHandler() noexcept": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 11, + "dels": 0 + } + }, + "size": null + }, "ConfigurationParser::ConfigurationParser(std::filesystem::path filePath)": { "files": [ "TextFileParsers.cpp" @@ -198,14 +238,49 @@ }, "size": null }, + "Exception::Exception()": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "Exception::~Exception() noexcept": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "InvalidCastException::InvalidCastException(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "RowReader &operator>>(RowReader &reader, bool &rhs)": { "files": [ - "TextFileParsers.cpp", - "TextFileParsers.h" + "TextFileParsers.cpp" ], "history": { "A": { - "adds": 25, + "adds": 24, "dels": 0 } }, @@ -213,12 +288,11 @@ }, "RowReader &operator>>(RowReader &reader, double &rhs)": { "files": [ - "TextFileParsers.cpp", - "TextFileParsers.h" + "TextFileParsers.cpp" ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -226,12 +300,11 @@ }, "RowReader &operator>>(RowReader &reader, float &rhs)": { "files": [ - "TextFileParsers.cpp", - "TextFileParsers.h" + "TextFileParsers.cpp" ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -239,12 +312,11 @@ }, "RowReader &operator>>(RowReader &reader, int &rhs)": { "files": [ - "TextFileParsers.cpp", - "TextFileParsers.h" + "TextFileParsers.cpp" ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -252,12 +324,11 @@ }, "RowReader &operator>>(RowReader &reader, long &rhs)": { "files": [ - "TextFileParsers.cpp", - "TextFileParsers.h" + "TextFileParsers.cpp" ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -265,12 +336,23 @@ }, "RowReader &operator>>(RowReader &reader, std::string &rhs)": { "files": [ - "TextFileParsers.cpp", + "TextFileParsers.cpp" + ], + "history": { + "A": { + "adds": 16, + "dels": 0 + } + }, + "size": null + }, + "RowReader::operator bool() const": { + "files": [ "TextFileParsers.h" ], "history": { "A": { - "adds": 17, + "adds": 4, "dels": 0 } }, @@ -312,6 +394,30 @@ }, "size": null }, + "TIterator _RangeToEnumerable::begin()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "TIterator _RangeToEnumerable::end()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "TStream &operator>>(TStream &s, RowReader &reader)": { "files": [ "TextFileParsers.h" @@ -372,6 +478,18 @@ }, "size": null }, + "_RangeToEnumerable::_RangeToEnumerable(const std::pair range)": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "_RangeToEnumerable RangeToEnumerable(const std::pair range)": { "files": [ "Utility.h" @@ -414,7 +532,7 @@ ], "history": { "A": { - "adds": 18, + "adds": 17, "dels": 0 } }, @@ -426,7 +544,31 @@ ], "history": { "A": { - "adds": 30, + "adds": 29, + "dels": 0 + } + }, + "size": null + }, + "bool RowReader::operator!() const": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "bool _RangeToEnumerable::empty()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, "dels": 0 } }, @@ -456,9 +598,9 @@ }, "size": null }, - "const char *FriendlyNameOf()": { + "const char *Exception::what() const noexcept": { "files": [ - "Utility.h" + "Exceptions.h" ], "history": { "A": { @@ -468,7 +610,7 @@ }, "size": null }, - "const char *FriendlyNameOf(const ReliabilityNetworkEntry &instance)": { + "const char *FriendlyNameOf()": { "files": [ "Utility.h" ], @@ -480,9 +622,9 @@ }, "size": null }, - "const char *FriendlyNameOf(const std::type_index &type)": { + "const std::string &ArgumentException::ArgumentName() const": { "files": [ - "Utility.h" + "Exceptions.h" ], "history": { "A": { @@ -492,9 +634,9 @@ }, "size": null }, - "const char *FriendlyNameOf(const type_info &type)": { + "const std::stringstream &RowReader::LineStream() const": { "files": [ - "Utility.h" + "TextFileParsers.h" ], "history": { "A": { @@ -528,6 +670,54 @@ }, "size": null }, + "explicit BlockExitHandler::BlockExitHandler(const std::function &handler)": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "explicit Exception::Exception(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 6, + "dels": 0 + } + }, + "size": null + }, + "explicit OperationFailureException::OperationFailureException(int errorCode)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "explicit RowReader::RowReader(bool keepWhitespace, char delim)": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 3, + "dels": 0 + } + }, + "size": null + }, "inline std::string to_string(const std::pair &value)": { "files": [ "Utility.h" @@ -568,6 +758,30 @@ }, "size": null }, + "size_t RowReader::LineNumber() const": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "static std::string ArgumentException::BuildMessage(const std::string &message, const std::string &argumentName)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 5, + "dels": 0 + } + }, + "size": null + }, "std::shared_ptr safe_pointer_cast(const std::shared_ptr &obj)": { "files": [ "Utility.h" @@ -622,7 +836,19 @@ ], "history": { "A": { - "adds": 21, + "adds": 20, + "dels": 0 + } + }, + "size": null + }, + "void RowReader::ResetLineNumber()": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 1, "dels": 0 } }, diff --git a/test/test_analytics/baseline/cpp_test_repo/C.g.json b/test/test_analytics/baseline/cpp_test_repo/C.g.json index 2e596bc9ef6..e8db0ec0531 100644 --- a/test/test_analytics/baseline/cpp_test_repo/C.g.json +++ b/test/test_analytics/baseline/cpp_test_repo/C.g.json @@ -1,5 +1,9 @@ { "edges": { + "ArgumentException::ArgumentException(const std::string &message, const std::string &argumentName)|->|static std::string ArgumentException::BuildMessage(const std::string &message, const std::string &argumentName)": { + "addedBy": "A", + "weight": null + }, "ConfigurationParser::ConfigurationParser(std::filesystem::path filePath)|->|TStream OpenAndValidate(const TPath arg1)": { "addedBy": "C", "weight": null @@ -28,30 +32,10 @@ "addedBy": "C", "weight": null }, - "bool Confirm(const std::string &prompt)|->|bool Confirm(const std::string &prompt)": { - "addedBy": "C", - "weight": null - }, - "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)|->|bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)": { - "addedBy": "C", - "weight": null - }, "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)|->|enum class StringComparison : int {}": { "addedBy": "C", "weight": null }, - "const char *FriendlyNameOf(const ReliabilityNetworkEntry &instance)|->|const char *FriendlyNameOf()": { - "addedBy": "C", - "weight": null - }, - "const char *FriendlyNameOf(const std::type_index &type)|->|const char *FriendlyNameOf()": { - "addedBy": "C", - "weight": null - }, - "const char *FriendlyNameOf(const type_info &type)|->|const char *FriendlyNameOf()": { - "addedBy": "C", - "weight": null - }, "int main(int argc, char *argv[])|->|TStream OpenAndValidate(const TPath arg1)": { "addedBy": "C", "weight": null @@ -71,10 +55,6 @@ "int main(int argc, char *argv[])|->|void ReportException(const std::exception &ex, int level)": { "addedBy": "B", "weight": null - }, - "void ReportException(const std::exception &ex, int level)|->|void ReportException(const std::exception &ex, int level)": { - "addedBy": "C", - "weight": null } }, "nodes": { @@ -174,6 +154,66 @@ }, "size": null }, + "ArgumentException::ArgumentException(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 2, + "dels": 0 + } + }, + "size": null + }, + "ArgumentException::ArgumentException(const std::string &message, const std::string &argumentName)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 2, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler &BlockExitHandler::operator=(const BlockExitHandler &) = delete": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler::BlockExitHandler(const BlockExitHandler &) = delete": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler::~BlockExitHandler() noexcept": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 11, + "dels": 0 + } + }, + "size": null + }, "ConfigurationParser::ConfigurationParser(std::filesystem::path filePath)": { "files": [ "TextFileParsers.cpp" @@ -198,13 +238,49 @@ }, "size": null }, + "Exception::Exception()": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "Exception::~Exception() noexcept": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "InvalidCastException::InvalidCastException(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "RowReader &operator>>(RowReader &reader, bool &rhs)": { "files": [ "TextFileParsers.cpp" ], "history": { "A": { - "adds": 25, + "adds": 24, "dels": 0 }, "C": { @@ -220,7 +296,7 @@ ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -232,7 +308,7 @@ ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -244,7 +320,7 @@ ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -256,7 +332,7 @@ ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -268,7 +344,19 @@ ], "history": { "A": { - "adds": 17, + "adds": 16, + "dels": 0 + } + }, + "size": null + }, + "RowReader::operator bool() const": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 4, "dels": 0 } }, @@ -310,6 +398,30 @@ }, "size": null }, + "TIterator _RangeToEnumerable::begin()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "TIterator _RangeToEnumerable::end()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "TStream &operator>>(TStream &s, RowReader &reader)": { "files": [ "TextFileParsers.h" @@ -370,6 +482,18 @@ }, "size": null }, + "_RangeToEnumerable::_RangeToEnumerable(const std::pair range)": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "_RangeToEnumerable RangeToEnumerable(const std::pair range)": { "files": [ "Utility.h" @@ -412,12 +536,11 @@ }, "bool Confirm(const std::string &prompt)": { "files": [ - "Utility.cpp", - "Utility.h" + "Utility.cpp" ], "history": { "A": { - "adds": 18, + "adds": 17, "dels": 0 } }, @@ -425,12 +548,11 @@ }, "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)": { "files": [ - "Utility.cpp", - "Utility.h" + "Utility.cpp" ], "history": { "A": { - "adds": 30, + "adds": 29, "dels": 0 }, "C": { @@ -440,6 +562,30 @@ }, "size": null }, + "bool RowReader::operator!() const": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "bool _RangeToEnumerable::empty()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "bool dynamic_kind_of(const TSrc *obj)": { "files": [ "Utility.h" @@ -464,9 +610,9 @@ }, "size": null }, - "const char *FriendlyNameOf()": { + "const char *Exception::what() const noexcept": { "files": [ - "Utility.h" + "Exceptions.h" ], "history": { "A": { @@ -476,7 +622,7 @@ }, "size": null }, - "const char *FriendlyNameOf(const ReliabilityNetworkEntry &instance)": { + "const char *FriendlyNameOf()": { "files": [ "Utility.h" ], @@ -488,9 +634,9 @@ }, "size": null }, - "const char *FriendlyNameOf(const std::type_index &type)": { + "const std::string &ArgumentException::ArgumentName() const": { "files": [ - "Utility.h" + "Exceptions.h" ], "history": { "A": { @@ -500,9 +646,9 @@ }, "size": null }, - "const char *FriendlyNameOf(const type_info &type)": { + "const std::stringstream &RowReader::LineStream() const": { "files": [ - "Utility.h" + "TextFileParsers.h" ], "history": { "A": { @@ -540,6 +686,54 @@ }, "size": null }, + "explicit BlockExitHandler::BlockExitHandler(const std::function &handler)": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "explicit Exception::Exception(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 6, + "dels": 0 + } + }, + "size": null + }, + "explicit OperationFailureException::OperationFailureException(int errorCode)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "explicit RowReader::RowReader(bool keepWhitespace, char delim)": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 3, + "dels": 0 + } + }, + "size": null + }, "inline std::string to_string(const std::pair &value)": { "files": [ "Utility.h" @@ -584,6 +778,30 @@ }, "size": null }, + "size_t RowReader::LineNumber() const": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "static std::string ArgumentException::BuildMessage(const std::string &message, const std::string &argumentName)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 5, + "dels": 0 + } + }, + "size": null + }, "std::shared_ptr safe_pointer_cast(const std::shared_ptr &obj)": { "files": [ "Utility.h" @@ -634,12 +852,23 @@ }, "void ReportException(const std::exception &ex, int level)": { "files": [ - "Utility.cpp", - "Utility.h" + "Utility.cpp" + ], + "history": { + "A": { + "adds": 20, + "dels": 0 + } + }, + "size": null + }, + "void RowReader::ResetLineNumber()": { + "files": [ + "TextFileParsers.h" ], "history": { "A": { - "adds": 21, + "adds": 1, "dels": 0 } }, diff --git a/test/test_analytics/baseline/cpp_test_repo/D.g.json b/test/test_analytics/baseline/cpp_test_repo/D.g.json index 02fe0fde492..e5eb44a4f6d 100644 --- a/test/test_analytics/baseline/cpp_test_repo/D.g.json +++ b/test/test_analytics/baseline/cpp_test_repo/D.g.json @@ -1,5 +1,9 @@ { "edges": { + "ArgumentException::ArgumentException(const std::string &message, const std::string &argumentName)|->|static std::string ArgumentException::BuildMessage(const std::string &message, const std::string &argumentName)": { + "addedBy": "A", + "weight": null + }, "ConfigurationParser::ConfigurationParser(std::filesystem::path filePath)|->|TStream OpenAndValidate(const TPath arg1)": { "addedBy": "D", "weight": null @@ -28,30 +32,10 @@ "addedBy": "D", "weight": null }, - "bool Confirm(const std::string &prompt)|->|bool Confirm(const std::string &prompt)": { - "addedBy": "D", - "weight": null - }, - "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)|->|bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)": { - "addedBy": "D", - "weight": null - }, "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)|->|enum class StringComparison : int {}": { "addedBy": "D", "weight": null }, - "const char *FriendlyNameOf(const ReliabilityNetworkEntry &instance)|->|const char *FriendlyNameOf()": { - "addedBy": "D", - "weight": null - }, - "const char *FriendlyNameOf(const std::type_index &type)|->|const char *FriendlyNameOf()": { - "addedBy": "D", - "weight": null - }, - "const char *FriendlyNameOf(const type_info &type)|->|const char *FriendlyNameOf()": { - "addedBy": "D", - "weight": null - }, "int main(int argc, char *argv[])|->|TStream OpenAndValidate(const TPath arg1)": { "addedBy": "C", "weight": null @@ -71,10 +55,6 @@ "int main(int argc, char *argv[])|->|void ReportException(const std::exception &ex, int level)": { "addedBy": "B", "weight": null - }, - "void ReportException(const std::exception &ex, int level)|->|void ReportException(const std::exception &ex, int level)": { - "addedBy": "D", - "weight": null } }, "nodes": { @@ -174,6 +154,66 @@ }, "size": null }, + "ArgumentException::ArgumentException(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 2, + "dels": 0 + } + }, + "size": null + }, + "ArgumentException::ArgumentException(const std::string &message, const std::string &argumentName)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 2, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler &BlockExitHandler::operator=(const BlockExitHandler &) = delete": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler::BlockExitHandler(const BlockExitHandler &) = delete": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "BlockExitHandler::~BlockExitHandler() noexcept": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 11, + "dels": 0 + } + }, + "size": null + }, "ConfigurationParser::ConfigurationParser(std::filesystem::path filePath)": { "files": [ "TextFileParsers.cpp" @@ -198,13 +238,49 @@ }, "size": null }, + "Exception::Exception()": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "Exception::~Exception() noexcept": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "InvalidCastException::InvalidCastException(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "RowReader &operator>>(RowReader &reader, bool &rhs)": { "files": [ "TextFileParsers.cpp" ], "history": { "A": { - "adds": 25, + "adds": 24, "dels": 0 }, "C": { @@ -224,7 +300,7 @@ ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -236,7 +312,7 @@ ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -248,7 +324,7 @@ ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -260,7 +336,7 @@ ], "history": { "A": { - "adds": 7, + "adds": 6, "dels": 0 } }, @@ -272,7 +348,19 @@ ], "history": { "A": { - "adds": 17, + "adds": 16, + "dels": 0 + } + }, + "size": null + }, + "RowReader::operator bool() const": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 4, "dels": 0 } }, @@ -314,6 +402,30 @@ }, "size": null }, + "TIterator _RangeToEnumerable::begin()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "TIterator _RangeToEnumerable::end()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "TStream &operator>>(TStream &s, RowReader &reader)": { "files": [ "TextFileParsers.h" @@ -374,6 +486,18 @@ }, "size": null }, + "_RangeToEnumerable::_RangeToEnumerable(const std::pair range)": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "_RangeToEnumerable RangeToEnumerable(const std::pair range)": { "files": [ "Utility.h" @@ -420,12 +544,11 @@ }, "bool Confirm(const std::string &prompt)": { "files": [ - "Utility.cpp", - "Utility.h" + "Utility.cpp" ], "history": { "A": { - "adds": 18, + "adds": 17, "dels": 0 } }, @@ -433,12 +556,11 @@ }, "bool Equal(const std::string &lhs, const std::string &rhs, StringComparison comparision)": { "files": [ - "Utility.cpp", - "Utility.h" + "Utility.cpp" ], "history": { "A": { - "adds": 30, + "adds": 29, "dels": 0 }, "C": { @@ -452,6 +574,30 @@ }, "size": null }, + "bool RowReader::operator!() const": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "bool _RangeToEnumerable::empty()": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, "bool dynamic_kind_of(const TSrc *obj)": { "files": [ "Utility.h" @@ -476,9 +622,9 @@ }, "size": null }, - "const char *FriendlyNameOf()": { + "const char *Exception::what() const noexcept": { "files": [ - "Utility.h" + "Exceptions.h" ], "history": { "A": { @@ -488,7 +634,7 @@ }, "size": null }, - "const char *FriendlyNameOf(const ReliabilityNetworkEntry &instance)": { + "const char *FriendlyNameOf()": { "files": [ "Utility.h" ], @@ -500,9 +646,9 @@ }, "size": null }, - "const char *FriendlyNameOf(const std::type_index &type)": { + "const std::string &ArgumentException::ArgumentName() const": { "files": [ - "Utility.h" + "Exceptions.h" ], "history": { "A": { @@ -512,9 +658,9 @@ }, "size": null }, - "const char *FriendlyNameOf(const type_info &type)": { + "const std::stringstream &RowReader::LineStream() const": { "files": [ - "Utility.h" + "TextFileParsers.h" ], "history": { "A": { @@ -556,6 +702,54 @@ }, "size": null }, + "explicit BlockExitHandler::BlockExitHandler(const std::function &handler)": { + "files": [ + "Utility.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "explicit Exception::Exception(const std::string &message)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 6, + "dels": 0 + } + }, + "size": null + }, + "explicit OperationFailureException::OperationFailureException(int errorCode)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 4, + "dels": 0 + } + }, + "size": null + }, + "explicit RowReader::RowReader(bool keepWhitespace, char delim)": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 3, + "dels": 0 + } + }, + "size": null + }, "inline std::string to_string(const std::pair &value)": { "files": [ "Utility.h" @@ -604,6 +798,30 @@ }, "size": null }, + "size_t RowReader::LineNumber() const": { + "files": [ + "TextFileParsers.h" + ], + "history": { + "A": { + "adds": 1, + "dels": 0 + } + }, + "size": null + }, + "static std::string ArgumentException::BuildMessage(const std::string &message, const std::string &argumentName)": { + "files": [ + "Exceptions.h" + ], + "history": { + "A": { + "adds": 5, + "dels": 0 + } + }, + "size": null + }, "std::shared_ptr safe_pointer_cast(const std::shared_ptr &obj)": { "files": [ "Utility.h" @@ -654,12 +872,23 @@ }, "void ReportException(const std::exception &ex, int level)": { "files": [ - "Utility.cpp", - "Utility.h" + "Utility.cpp" + ], + "history": { + "A": { + "adds": 20, + "dels": 0 + } + }, + "size": null + }, + "void RowReader::ResetLineNumber()": { + "files": [ + "TextFileParsers.h" ], "history": { "A": { - "adds": 21, + "adds": 1, "dels": 0 } }, diff --git a/test/test_analytics/baseline/feature_branch/C.g.json b/test/test_analytics/baseline/feature_branch/C.g.json index 4b791785f4e..9992cb0fd09 100644 --- a/test/test_analytics/baseline/feature_branch/C.g.json +++ b/test/test_analytics/baseline/feature_branch/C.g.json @@ -1,6 +1,6 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "C", "weight": null }, @@ -42,13 +42,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch/D.g.json b/test/test_analytics/baseline/feature_branch/D.g.json index 4b931b0a2c0..488d426a937 100644 --- a/test/test_analytics/baseline/feature_branch/D.g.json +++ b/test/test_analytics/baseline/feature_branch/D.g.json @@ -1,6 +1,6 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "D", "weight": null }, @@ -66,13 +66,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch/E.g.json b/test/test_analytics/baseline/feature_branch/E.g.json index 414ed9fd459..26ef09a68c0 100644 --- a/test/test_analytics/baseline/feature_branch/E.g.json +++ b/test/test_analytics/baseline/feature_branch/E.g.json @@ -1,6 +1,6 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "D", "weight": null }, @@ -74,13 +74,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch/F.g.json b/test/test_analytics/baseline/feature_branch/F.g.json index 31a14cda404..4c8ee3397cc 100644 --- a/test/test_analytics/baseline/feature_branch/F.g.json +++ b/test/test_analytics/baseline/feature_branch/F.g.json @@ -4,7 +4,7 @@ "addedBy": "F", "weight": null }, - "char *str_append_chr(char *string, char append)|->|int str_equals()": { + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "F", "weight": null }, @@ -16,12 +16,8 @@ "addedBy": "F", "weight": null }, - "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals()": { - "addedBy": "F", - "weight": null - }, "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals(char *equal1, char *eqaul2)": { - "addedBy": "G", + "addedBy": "F", "weight": null }, "char *str_replace(char *search, char *replace, char *subject)|->|int str_len(char *string)": { @@ -94,13 +90,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch/G.g.json b/test/test_analytics/baseline/feature_branch/G.g.json index 9be01d4cc7f..e933b06f594 100644 --- a/test/test_analytics/baseline/feature_branch/G.g.json +++ b/test/test_analytics/baseline/feature_branch/G.g.json @@ -1,6 +1,6 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "C", "weight": null }, @@ -66,13 +66,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch/H.g.json b/test/test_analytics/baseline/feature_branch/H.g.json index 8089ef9ccbf..6d72823868b 100644 --- a/test/test_analytics/baseline/feature_branch/H.g.json +++ b/test/test_analytics/baseline/feature_branch/H.g.json @@ -1,6 +1,6 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "D", "weight": null }, @@ -74,13 +74,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch/I.g.json b/test/test_analytics/baseline/feature_branch/I.g.json index 414ed9fd459..26ef09a68c0 100644 --- a/test/test_analytics/baseline/feature_branch/I.g.json +++ b/test/test_analytics/baseline/feature_branch/I.g.json @@ -1,6 +1,6 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "D", "weight": null }, @@ -74,13 +74,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch/J.g.json b/test/test_analytics/baseline/feature_branch/J.g.json index 7606ab45a52..ae29e94aeef 100644 --- a/test/test_analytics/baseline/feature_branch/J.g.json +++ b/test/test_analytics/baseline/feature_branch/J.g.json @@ -1,6 +1,6 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "D", "weight": null }, @@ -86,13 +86,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch/K.g.json b/test/test_analytics/baseline/feature_branch/K.g.json index 555bdff3d1e..c406a16e2d7 100644 --- a/test/test_analytics/baseline/feature_branch/K.g.json +++ b/test/test_analytics/baseline/feature_branch/K.g.json @@ -4,7 +4,7 @@ "addedBy": "F", "weight": null }, - "char *str_append_chr(char *string, char append)|->|int str_equals()": { + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "F", "weight": null }, @@ -16,12 +16,8 @@ "addedBy": "F", "weight": null }, - "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals()": { - "addedBy": "F", - "weight": null - }, "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals(char *equal1, char *eqaul2)": { - "addedBy": "G", + "addedBy": "F", "weight": null }, "char *str_replace(char *search, char *replace, char *subject)|->|int str_len(char *string)": { @@ -94,13 +90,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch_first_parent/C.g.json b/test/test_analytics/baseline/feature_branch_first_parent/C.g.json index 4b791785f4e..9992cb0fd09 100644 --- a/test/test_analytics/baseline/feature_branch_first_parent/C.g.json +++ b/test/test_analytics/baseline/feature_branch_first_parent/C.g.json @@ -1,6 +1,6 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "C", "weight": null }, @@ -42,13 +42,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch_first_parent/D.g.json b/test/test_analytics/baseline/feature_branch_first_parent/D.g.json index f289e724860..a1579f2d346 100644 --- a/test/test_analytics/baseline/feature_branch_first_parent/D.g.json +++ b/test/test_analytics/baseline/feature_branch_first_parent/D.g.json @@ -1,18 +1,18 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { - "addedBy": "C", + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { + "addedBy": "D", "weight": null }, "char *str_append_chr(char *string, char append)|->|int str_len(char *string)": { - "addedBy": "C", + "addedBy": "D", "weight": null }, "char *str_replace(char *search, char *replace, char *subject)|->|char *str_append_chr(char *string, char append)": { "addedBy": "D", "weight": null }, - "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals()": { + "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "D", "weight": null }, @@ -66,13 +66,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch_first_parent/E.g.json b/test/test_analytics/baseline/feature_branch_first_parent/E.g.json index 8d6ec786302..3c24ccfc482 100644 --- a/test/test_analytics/baseline/feature_branch_first_parent/E.g.json +++ b/test/test_analytics/baseline/feature_branch_first_parent/E.g.json @@ -1,18 +1,18 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { - "addedBy": "C", + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { + "addedBy": "D", "weight": null }, "char *str_append_chr(char *string, char append)|->|int str_len(char *string)": { - "addedBy": "C", + "addedBy": "D", "weight": null }, "char *str_replace(char *search, char *replace, char *subject)|->|char *str_append_chr(char *string, char append)": { "addedBy": "D", "weight": null }, - "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals()": { + "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "D", "weight": null }, @@ -66,13 +66,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch_first_parent/F.g.json b/test/test_analytics/baseline/feature_branch_first_parent/F.g.json index da60e2d5a1b..1ea3182ab6d 100644 --- a/test/test_analytics/baseline/feature_branch_first_parent/F.g.json +++ b/test/test_analytics/baseline/feature_branch_first_parent/F.g.json @@ -1,18 +1,18 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { - "addedBy": "C", + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { + "addedBy": "D", "weight": null }, "char *str_append_chr(char *string, char append)|->|int str_len(char *string)": { - "addedBy": "C", + "addedBy": "D", "weight": null }, "char *str_replace(char *search, char *replace, char *subject)|->|char *str_append_chr(char *string, char append)": { "addedBy": "D", "weight": null }, - "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals()": { + "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "D", "weight": null }, @@ -78,13 +78,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/baseline/feature_branch_first_parent/K.g.json b/test/test_analytics/baseline/feature_branch_first_parent/K.g.json index 1c8c8e2e3a9..32ca12c74da 100644 --- a/test/test_analytics/baseline/feature_branch_first_parent/K.g.json +++ b/test/test_analytics/baseline/feature_branch_first_parent/K.g.json @@ -1,18 +1,18 @@ { "edges": { - "char *str_append_chr(char *string, char append)|->|int str_equals()": { - "addedBy": "C", + "char *str_append_chr(char *string, char append)|->|int str_equals(char *equal1, char *eqaul2)": { + "addedBy": "D", "weight": null }, "char *str_append_chr(char *string, char append)|->|int str_len(char *string)": { - "addedBy": "C", + "addedBy": "D", "weight": null }, "char *str_replace(char *search, char *replace, char *subject)|->|char *str_append_chr(char *string, char append)": { "addedBy": "D", "weight": null }, - "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals()": { + "char *str_replace(char *search, char *replace, char *subject)|->|int str_equals(char *equal1, char *eqaul2)": { "addedBy": "D", "weight": null }, @@ -78,13 +78,6 @@ }, "size": null }, - "int str_equals()": { - "files": [ - "main.c" - ], - "history": {}, - "size": null - }, "int str_equals(char *equal1, char *eqaul2)": { "files": [ "main.c" diff --git a/test/test_analytics/test_analyzer_lsp_ccls.py b/test/test_analytics/test_analyzer_lsp_ccls.py index 0b903fb9e2e..33d17e06f32 100644 --- a/test/test_analytics/test_analyzer_lsp_ccls.py +++ b/test/test_analytics/test_analyzer_lsp_ccls.py @@ -1,10 +1,10 @@ import json import logging import os +import pickle import subprocess from pathlib import Path from tempfile import mkdtemp -from .utility.graph_baseline import GraphDumpAnalyzerObserver import networkx.readwrite.json_graph import pytest @@ -17,6 +17,11 @@ from persper.analytics.lsp_graph_server.ccls import CclsGraphServer from persper.util.path import root_path +from .utility.graph_baseline import GraphDumpAnalyzerObserver + +# Whether we are generating graph dump baseline, rather than testing for regression. +IS_GENERATING_BASELINE = True + _logger = logging.getLogger() testDataRoot = os.path.dirname(os.path.abspath(__file__)) @@ -49,6 +54,14 @@ def createCclsGraphServer(): return graphServer +def createGraphDumpAnalyzerObserver(testName: str): + return GraphDumpAnalyzerObserver( + None if IS_GENERATING_BASELINE else + os.path.join(testDataRoot, "baseline/" + testName), + os.path.join(testDataRoot, "actualdump/" + testName), + dumpNaming=CommitIdGenerators.fromComment) + + @pytest.mark.asyncio async def testFeatureBranchFirstParent(): """ @@ -58,9 +71,8 @@ async def testFeatureBranchFirstParent(): graphServer = createCclsGraphServer() analyzer = Analyzer(repoPath, graphServer, firstParentOnly=True) async with graphServer: - analyzer.observer = GraphDumpAnalyzerObserver( - os.path.join(testDataRoot, "baseline/feature_branch_first_parent"), - os.path.join(testDataRoot, "actualdump/feature_branch_first_parent")) + analyzer.observer = createGraphDumpAnalyzerObserver( + "feature_branch_first_parent") await analyzer.analyze() @@ -73,9 +85,7 @@ async def testFeatureBranch(): graphServer = createCclsGraphServer() analyzer = Analyzer(repoPath, graphServer, firstParentOnly=False) async with graphServer: - analyzer.observer = GraphDumpAnalyzerObserver( - os.path.join(testDataRoot, "baseline/feature_branch"), - os.path.join(testDataRoot, "actualdump/feature_branch")) + analyzer.observer = createGraphDumpAnalyzerObserver("feature_branch") await analyzer.analyze() @@ -85,7 +95,30 @@ async def testCppTestRepo(): graphServer = createCclsGraphServer() analyzer = Analyzer(repoPath, graphServer) async with graphServer: - analyzer.observer = GraphDumpAnalyzerObserver( - os.path.join(testDataRoot, "baseline/cpp_test_repo"), - os.path.join(testDataRoot, "actualdump/cpp_test_repo")) + analyzer.observer = createGraphDumpAnalyzerObserver("cpp_test_repo") await analyzer.analyze() + + +@pytest.mark.asyncio +async def testAnalyzerWithPickle(): + repoPath = prepareRepo("test_feature_branch") + graphServer = createCclsGraphServer() + analyzer = Analyzer(repoPath, graphServer) + pickleContent = None + async with graphServer: + analyzer.observer = createGraphDumpAnalyzerObserver( + "analyzer_pickling") + assert len(analyzer.visitedCommits) == 0 + await analyzer.analyze(2) + assert len(analyzer.visitedCommits) == 2 + await analyzer.analyze(2) + assert len(analyzer.visitedCommits) == 4 + pickleContent = pickle.dumps(analyzer) + + analyzer1: Analyzer = pickle.loads(pickleContent) + # Perhaps we need to set another temp folder for this. + graphServer1 = analyzer1.graphServer + analyzer1.observer = analyzer.observer + async with graphServer1: + assert analyzer1.visitedCommits == analyzer.visitedCommits + await analyzer1.analyze() diff --git a/test/test_analytics/utility/graph_baseline.py b/test/test_analytics/utility/graph_baseline.py index 8323f5455a5..96527e86e8b 100644 --- a/test/test_analytics/utility/graph_baseline.py +++ b/test/test_analytics/utility/graph_baseline.py @@ -11,7 +11,7 @@ from networkx import Graph from persper.analytics.analyzer2 import Analyzer, AnalyzerObserver -from persper.analytics.call_commit_graph import CallCommitGraph +from persper.analytics.call_commit_graph import CallCommitGraph, CommitIdGenerators from persper.analytics.graph_server import CommitSeekingMode _logger = logging.getLogger() @@ -66,12 +66,6 @@ def assertGraphMatches(baseline: dict, ccg: CallCommitGraph): assert not baselineEdgeIds, str.format( "Branch(es) missing: {0}.", baselineEdgeIds) - -class GraphDumpNamingRule(Enum): - CommitMessage = 0, - CommitHexSha = 1 - - class GraphDumpAnalyzerObserver(AnalyzerObserver): """ An implementation of AnalyzerObserver that generates graph dump after each commit, @@ -79,7 +73,7 @@ class GraphDumpAnalyzerObserver(AnalyzerObserver): """ def __init__(self, graphBaselineDumpPath: str = None, graphTestDumpPath: str = None, - dumpOnlyOnError: bool = None, dumpNaming: GraphDumpNamingRule = GraphDumpNamingRule.CommitHexSha): + dumpOnlyOnError: bool = None, dumpNaming = CommitIdGenerators.fromHexsha): """ Params: graphBaselineDumpPath: root folder of the baseline graph dump files. Set to values other than `None` @@ -105,11 +99,13 @@ def __init__(self, graphBaselineDumpPath: str = None, graphTestDumpPath: str = N else: self._dumpPath = None self._dumpOnlyOnError = graphBaselineDumpPath != None if dumpOnlyOnError == None else dumpOnlyOnError + self._dumpNaming = dumpNaming def onAfterCommit(self, analyzer: Analyzer, commit: Commit, seeking_mode: CommitSeekingMode): if seeking_mode == CommitSeekingMode.Rewind: return graph: CallCommitGraph = analyzer.graph + graphDumpLocalName = self._dumpNaming(-1, commit.hexsha, commit.message) + ".g.json" def dumpGraph(warnIfNotAvailable: bool): if not self._dumpPath: @@ -118,16 +114,14 @@ def dumpGraph(warnIfNotAvailable: bool): "Cannot dump call commit graph because no dump path has been specified. Commit %s: %s.", commit.hexsha, commit.message) return False data = graphToDict(graph) - graphPath = self._dumpPath.joinpath( - commit.message.strip() + ".g.json") + graphPath = self._dumpPath.joinpath(graphDumpLocalName) with open(graphPath, "wt") as f: json.dump(data, f, sort_keys=True, indent=4) return True # check baseline for regression if self._baselinePath: try: - graphPath = self._baselinePath.joinpath( - commit.message.strip() + ".g.json") + graphPath = self._baselinePath.joinpath(graphDumpLocalName) baselineData: dict = None with open(graphPath, "rt") as f: baselineData = fixGraphDict(json.load(f)) diff --git a/test/test_feature_branch/C/main.c b/test/test_feature_branch/C/main.c index 401fb0597d6..5eaeabc97a7 100644 --- a/test/test_feature_branch/C/main.c +++ b/test/test_feature_branch/C/main.c @@ -8,6 +8,8 @@ int str_len(char *string) /* str_append is deleted in B */ +int str_equals(char *equal1, char *eqaul2); // Forward decl. + /* added in B, edited in C */ char* str_append_chr(char* string, char append) { char* newstring = ""; diff --git a/test/test_feature_branch/D/main.c b/test/test_feature_branch/D/main.c index 401fb0597d6..c5a80c50643 100644 --- a/test/test_feature_branch/D/main.c +++ b/test/test_feature_branch/D/main.c @@ -8,6 +8,8 @@ int str_len(char *string) /* str_append is deleted in B */ +int str_equals(char *equal1, char *eqaul2); // Forward decl + /* added in B, edited in C */ char* str_append_chr(char* string, char append) { char* newstring = ""; diff --git a/test/test_feature_branch/E/main.c b/test/test_feature_branch/E/main.c index 401fb0597d6..c5a80c50643 100644 --- a/test/test_feature_branch/E/main.c +++ b/test/test_feature_branch/E/main.c @@ -8,6 +8,8 @@ int str_len(char *string) /* str_append is deleted in B */ +int str_equals(char *equal1, char *eqaul2); // Forward decl + /* added in B, edited in C */ char* str_append_chr(char* string, char append) { char* newstring = ""; diff --git a/test/test_feature_branch/F/main.c b/test/test_feature_branch/F/main.c index 401fb0597d6..c5a80c50643 100644 --- a/test/test_feature_branch/F/main.c +++ b/test/test_feature_branch/F/main.c @@ -8,6 +8,8 @@ int str_len(char *string) /* str_append is deleted in B */ +int str_equals(char *equal1, char *eqaul2); // Forward decl + /* added in B, edited in C */ char* str_append_chr(char* string, char append) { char* newstring = ""; diff --git a/test/test_feature_branch/G/main.c b/test/test_feature_branch/G/main.c index 19d8834f11f..67f1d720f3a 100644 --- a/test/test_feature_branch/G/main.c +++ b/test/test_feature_branch/G/main.c @@ -8,6 +8,8 @@ int str_len(char *string) /* str_append is deleted in B */ +int str_equals(char *equal1, char *eqaul2); // Forward decl + /* added in B*/ char* str_append_chr(char* string, char append) { char* newstring = NULL; diff --git a/test/test_feature_branch/H/main.c b/test/test_feature_branch/H/main.c index 401fb0597d6..c5a80c50643 100644 --- a/test/test_feature_branch/H/main.c +++ b/test/test_feature_branch/H/main.c @@ -8,6 +8,8 @@ int str_len(char *string) /* str_append is deleted in B */ +int str_equals(char *equal1, char *eqaul2); // Forward decl + /* added in B, edited in C */ char* str_append_chr(char* string, char append) { char* newstring = ""; diff --git a/test/test_feature_branch/I/main.c b/test/test_feature_branch/I/main.c index 401fb0597d6..c5a80c50643 100644 --- a/test/test_feature_branch/I/main.c +++ b/test/test_feature_branch/I/main.c @@ -8,6 +8,8 @@ int str_len(char *string) /* str_append is deleted in B */ +int str_equals(char *equal1, char *eqaul2); // Forward decl + /* added in B, edited in C */ char* str_append_chr(char* string, char append) { char* newstring = ""; diff --git a/test/test_feature_branch/K/main.c b/test/test_feature_branch/K/main.c index 401fb0597d6..c5a80c50643 100644 --- a/test/test_feature_branch/K/main.c +++ b/test/test_feature_branch/K/main.c @@ -8,6 +8,8 @@ int str_len(char *string) /* str_append is deleted in B */ +int str_equals(char *equal1, char *eqaul2); // Forward decl + /* added in B, edited in C */ char* str_append_chr(char* string, char append) { char* newstring = "";