data: saving graph nodes with short name only
This change saves only the short names in the node, getName() no only gives the short version. The fullName is assembled from the parent nodes on demand using the getFullName() method.
This commit is contained in:
@@ -238,26 +238,23 @@ void Storage::onGlobalVariableUsageParsed(
|
||||
addTokenLocation(edge, location);
|
||||
}
|
||||
|
||||
Id Storage::getIdForNodeWithName(const std::string& name) const
|
||||
Id Storage::getIdForNodeWithName(const std::string& fullName) const
|
||||
{
|
||||
Node* node = m_graph.findNode([&](Node* node){
|
||||
return node->getName() == name;
|
||||
});
|
||||
|
||||
Node* node = m_graph.getNode(fullName);
|
||||
return (node ? node->getId() : 0);
|
||||
}
|
||||
|
||||
std::string Storage::getNameForNodeWithId(Id id) const
|
||||
{
|
||||
Node* node = m_graph.getNodeById(id);
|
||||
return (node ? node->getName() : "");
|
||||
return (node ? node->getFullName() : "");
|
||||
}
|
||||
|
||||
std::vector<std::string> Storage::getNamesForNodesWithNamePrefix(const std::string& prefix) const
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
m_graph.forEachNode([&](Node* node){
|
||||
const std::string& nodeName = node->getName();
|
||||
const std::string& nodeName = node->getFullName();
|
||||
if (utility::isPrefix(prefix, nodeName))
|
||||
{
|
||||
names.push_back(nodeName);
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
const ParseLocation& location, const std::string& userName, const std::string& usedName);
|
||||
|
||||
// GraphAccess implementation
|
||||
virtual Id getIdForNodeWithName(const std::string& name) const;
|
||||
virtual Id getIdForNodeWithName(const std::string& fullName) const;
|
||||
virtual std::string getNameForNodeWithId(Id id) const;
|
||||
virtual std::vector<std::string> getNamesForNodesWithNamePrefix(const std::string& prefix) const;
|
||||
virtual std::vector<Id> getIdsOfNeighbours(const Id id) const;
|
||||
|
||||
@@ -16,12 +16,15 @@ Graph::~Graph()
|
||||
|
||||
Node* Graph::getNode(const std::string& fullName) const
|
||||
{
|
||||
return findNode(
|
||||
[fullName](Node* n)
|
||||
{
|
||||
return n->getName() == fullName;
|
||||
}
|
||||
);
|
||||
std::deque<std::string> names = utility::split<std::deque<std::string>>(fullName, DELIMITER);
|
||||
Node* node = getLastValidNode(&names);
|
||||
|
||||
if (node && !names.size())
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Edge* Graph::getEdge(Edge::EdgeType type, Node* from, Node* to) const
|
||||
@@ -71,8 +74,9 @@ Node* Graph::createNodeHierarchy(const std::string& fullName)
|
||||
|
||||
Node* Graph::createNodeHierarchy(Node::NodeType type, const std::string& fullName)
|
||||
{
|
||||
Node* node = getNode(fullName);
|
||||
if (node)
|
||||
std::deque<std::string> names = utility::split<std::deque<std::string>>(fullName, DELIMITER);
|
||||
Node* node = getLastValidNode(&names);
|
||||
if (node && !names.size())
|
||||
{
|
||||
if (type != Node::NODE_UNDEFINED)
|
||||
{
|
||||
@@ -81,7 +85,7 @@ Node* Graph::createNodeHierarchy(Node::NodeType type, const std::string& fullNam
|
||||
return node;
|
||||
}
|
||||
|
||||
return insertNodeHierarchy(type, fullName);
|
||||
return insertNodeHierarchy(type, names, node);
|
||||
}
|
||||
|
||||
Node* Graph::createNodeHierarchyWithDistinctSignature(const std::string& fullName, const std::string& signature)
|
||||
@@ -92,10 +96,12 @@ Node* Graph::createNodeHierarchyWithDistinctSignature(const std::string& fullNam
|
||||
Node* Graph::createNodeHierarchyWithDistinctSignature(
|
||||
Node::NodeType type, const std::string& fullName, const std::string& signature
|
||||
){
|
||||
Node* node = getNode(fullName);
|
||||
if (node)
|
||||
std::deque<std::string> names = utility::split<std::deque<std::string>>(fullName, DELIMITER);
|
||||
Node* node = getLastValidNode(&names);
|
||||
if (node && !names.size())
|
||||
{
|
||||
if (node->getComponent<TokenComponentSignature>()->getSignature() == signature)
|
||||
TokenComponentSignature* sigComponent = node->getComponent<TokenComponentSignature>();
|
||||
if (sigComponent && sigComponent->getSignature() == signature)
|
||||
{
|
||||
if (type != Node::NODE_UNDEFINED)
|
||||
{
|
||||
@@ -104,11 +110,35 @@ Node* Graph::createNodeHierarchyWithDistinctSignature(
|
||||
return node;
|
||||
}
|
||||
|
||||
node = insertNode(type, fullName, node->getParentNode());
|
||||
Node* parentNode = node->getParentNode();
|
||||
const std::string& name = node->getName();
|
||||
|
||||
std::function<bool(Node*)> findSignature =
|
||||
[&name, &signature](Node* n)
|
||||
{
|
||||
TokenComponentSignature* c = n->getComponent<TokenComponentSignature>();
|
||||
return n->getName() == name && c && c->getSignature() == signature;
|
||||
};
|
||||
|
||||
if (parentNode)
|
||||
{
|
||||
node = parentNode->findChildNode(findSignature);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = findNode(findSignature);
|
||||
}
|
||||
|
||||
if (node)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
node = insertNode(type, name, parentNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = insertNodeHierarchy(type, fullName);
|
||||
node = insertNodeHierarchy(type, names, node);
|
||||
}
|
||||
|
||||
node->addComponentSignature(std::make_shared<TokenComponentSignature>(signature));
|
||||
@@ -311,43 +341,60 @@ Edge* Graph::addEdgeAsPlainCopy(Edge* edge)
|
||||
|
||||
const std::string Graph::DELIMITER = "::";
|
||||
|
||||
Node* Graph::insertNodeHierarchy(Node::NodeType type, const std::string& fullName)
|
||||
Node* Graph::getLastValidNode(std::deque<std::string>* names) const
|
||||
{
|
||||
Node* node = nullptr;
|
||||
std::vector<std::string> names = utility::split(fullName, DELIMITER);
|
||||
std::string name;
|
||||
const std::string& name = names->front();
|
||||
|
||||
for (size_t i = 0; i < names.size(); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
Node* node = findNode(
|
||||
[&name](Node* n)
|
||||
{
|
||||
name += DELIMITER;
|
||||
return n->getName() == name && n->getParentNode() == nullptr;
|
||||
}
|
||||
name += names[i];
|
||||
);
|
||||
|
||||
Node* childNode = getNode(name);
|
||||
if (!node)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
names->pop_front();
|
||||
|
||||
while (names->size())
|
||||
{
|
||||
const std::string& name = names->front();
|
||||
Node* childNode = node->findChildNode(
|
||||
[&name](Node* n)
|
||||
{
|
||||
return n->getName() == name;
|
||||
}
|
||||
);
|
||||
|
||||
if (!childNode)
|
||||
{
|
||||
if (i == names.size() - 1)
|
||||
{
|
||||
childNode = insertNode(type, name, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
childNode = insertNode(Node::NODE_UNDEFINED, name, node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
node = childNode;
|
||||
names->pop_front();
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
Node* Graph::insertNode(Node::NodeType type, const std::string& fullName, Node* parentNode)
|
||||
Node* Graph::insertNodeHierarchy(Node::NodeType type, std::deque<std::string> names, Node* parentNode)
|
||||
{
|
||||
std::shared_ptr<Node> nodePtr = std::make_shared<Node>(type, fullName);
|
||||
while (names.size())
|
||||
{
|
||||
parentNode = insertNode(names.size() == 1 ? type : Node::NODE_UNDEFINED, names.front(), parentNode);
|
||||
names.pop_front();
|
||||
}
|
||||
|
||||
return parentNode;
|
||||
}
|
||||
|
||||
Node* Graph::insertNode(Node::NodeType type, const std::string& name, Node* parentNode)
|
||||
{
|
||||
std::shared_ptr<Node> nodePtr = std::make_shared<Node>(type, name);
|
||||
m_nodes.push_back(nodePtr);
|
||||
|
||||
Node* node = nodePtr.get();
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
#define GRAPH_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
#include "data/graph/Edge.h"
|
||||
#include "data/graph/Node.h"
|
||||
@@ -54,8 +55,9 @@ protected:
|
||||
private:
|
||||
static const std::string DELIMITER;
|
||||
|
||||
Node* insertNodeHierarchy(Node::NodeType type, const std::string& fullName);
|
||||
Node* insertNode(Node::NodeType type, const std::string& fullName, Node* parentNode);
|
||||
Node* getLastValidNode(std::deque<std::string>* names) const;
|
||||
Node* insertNodeHierarchy(Node::NodeType type, std::deque<std::string> names, Node* parentNode);
|
||||
Node* insertNode(Node::NodeType type, const std::string& name, Node* parentNode);
|
||||
Edge* insertEdge(Edge::EdgeType type, Node* from, Node* to);
|
||||
void removeEdgeInternal(Edge* edge);
|
||||
|
||||
|
||||
@@ -46,6 +46,19 @@ const std::string& Node::getName() const
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::string Node::getFullName() const
|
||||
{
|
||||
Node* parent = getParentNode();
|
||||
if (parent)
|
||||
{
|
||||
return parent->getFullName() + "::" + m_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<Edge*>& Node::getEdges() const
|
||||
{
|
||||
return m_edges;
|
||||
@@ -90,7 +103,7 @@ Edge* Node::findEdge(std::function<bool(Edge*)> func) const
|
||||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Edge* Node::findEdgeOfType(Edge::EdgeType type) const
|
||||
@@ -116,7 +129,28 @@ Edge* Node::findEdgeOfType(Edge::EdgeType type, std::function<bool(Edge*)> func)
|
||||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Node* Node::findChildNode(std::function<bool(Node*)> func) const
|
||||
{
|
||||
std::vector<Edge*>::const_iterator it = find_if(m_edges.begin(), m_edges.end(),
|
||||
[&func](Edge* e)
|
||||
{
|
||||
if (e->getType() == Edge::EDGE_MEMBER)
|
||||
{
|
||||
return func(e->getTo());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
if (it != m_edges.end())
|
||||
{
|
||||
return (*it)->getTo();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Node::forEachEdge(std::function<void(Edge*)> func) const
|
||||
@@ -137,6 +171,16 @@ void Node::forEachEdgeOfType(Edge::EdgeType type, std::function<void(Edge*)> fun
|
||||
);
|
||||
}
|
||||
|
||||
void Node::forEachChildNode(std::function<void(Node*)> func) const
|
||||
{
|
||||
forEachEdgeOfType(Edge::EDGE_MEMBER,
|
||||
[func](Edge* e)
|
||||
{
|
||||
func(e->getTo());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
bool Node::isNode() const
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -38,6 +38,8 @@ public:
|
||||
void setType(NodeType type);
|
||||
|
||||
const std::string& getName() const;
|
||||
std::string getFullName() const;
|
||||
|
||||
const std::vector<Edge*>& getEdges() const;
|
||||
|
||||
void addEdge(Edge* edge);
|
||||
@@ -49,9 +51,11 @@ public:
|
||||
Edge* findEdge(std::function<bool(Edge*)> func) const;
|
||||
Edge* findEdgeOfType(Edge::EdgeType type) const;
|
||||
Edge* findEdgeOfType(Edge::EdgeType type, std::function<bool(Edge*)> func) const;
|
||||
Node* findChildNode(std::function<bool(Node*)> func) const;
|
||||
|
||||
void forEachEdge(std::function<void(Edge*)> func) const;
|
||||
void forEachEdgeOfType(Edge::EdgeType type, std::function<void(Edge*)> func) const;
|
||||
void forEachChildNode(std::function<void(Node*)> func) const;
|
||||
|
||||
// Token implementation.
|
||||
virtual bool isNode() const;
|
||||
|
||||
@@ -2,28 +2,6 @@
|
||||
|
||||
namespace utility
|
||||
{
|
||||
std::vector<std::string> split(const std::string& str, char delimiter)
|
||||
{
|
||||
return split(str, std::string(1, delimiter));
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string& str, const std::string& delimiter)
|
||||
{
|
||||
size_t pos = 0;
|
||||
size_t oldPos = 0;
|
||||
std::vector<std::string> vec;
|
||||
|
||||
do
|
||||
{
|
||||
pos = str.find(delimiter, oldPos);
|
||||
vec.push_back(str.substr(oldPos, pos - oldPos));
|
||||
oldPos = pos + delimiter.size();
|
||||
}
|
||||
while (pos != std::string::npos);
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
bool isPrefix(const std::string& prefix, const std::string& text)
|
||||
{
|
||||
typedef std::pair<std::string::const_iterator, std::string::const_iterator> ResType;
|
||||
|
||||
@@ -6,10 +6,37 @@
|
||||
|
||||
namespace utility
|
||||
{
|
||||
std::vector<std::string> split(const std::string& str, char delimiter);
|
||||
std::vector<std::string> split(const std::string& str, const std::string& delimiter);
|
||||
template<typename ContainerType = std::vector<std::string>>
|
||||
ContainerType split(const std::string& str, char delimiter);
|
||||
|
||||
template<typename ContainerType = std::vector<std::string>>
|
||||
ContainerType split(const std::string& str, const std::string& delimiter);
|
||||
|
||||
bool isPrefix(const std::string& prefix, const std::string& text);
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
ContainerType utility::split(const std::string& str, char delimiter)
|
||||
{
|
||||
return split<ContainerType>(str, std::string(1, delimiter));
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
ContainerType utility::split(const std::string& str, const std::string& delimiter)
|
||||
{
|
||||
size_t pos = 0;
|
||||
size_t oldPos = 0;
|
||||
ContainerType c;
|
||||
|
||||
do
|
||||
{
|
||||
pos = str.find(delimiter, oldPos);
|
||||
c.push_back(str.substr(oldPos, pos - oldPos));
|
||||
oldPos = pos + delimiter.size();
|
||||
}
|
||||
while (pos != std::string::npos);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif // UTILITY_STRING_H
|
||||
|
||||
@@ -169,6 +169,64 @@ public:
|
||||
TS_ASSERT_EQUALS(e.getType(), e2.getType());
|
||||
}
|
||||
|
||||
void test_node_finds_child_node()
|
||||
{
|
||||
Node a(Node::NODE_UNDEFINED, "A");
|
||||
Node b(Node::NODE_UNDEFINED, "B");
|
||||
Node c(Node::NODE_UNDEFINED, "C");
|
||||
Edge e(Edge::EDGE_MEMBER, &a, &b);
|
||||
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
||||
|
||||
Node* x = a.findChildNode(
|
||||
[](Node* n)
|
||||
{
|
||||
return n->getName() == "C";
|
||||
}
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(x, &c);
|
||||
TS_ASSERT_DIFFERS(x, &b);
|
||||
}
|
||||
|
||||
void test_node_can_not_find_child_node()
|
||||
{
|
||||
Node a(Node::NODE_UNDEFINED, "A");
|
||||
Node b(Node::NODE_UNDEFINED, "B");
|
||||
Node c(Node::NODE_UNDEFINED, "C");
|
||||
Edge e(Edge::EDGE_MEMBER, &a, &b);
|
||||
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
||||
|
||||
Node* x = a.findChildNode(
|
||||
[](Node* n)
|
||||
{
|
||||
return n->getName() == "D";
|
||||
}
|
||||
);
|
||||
|
||||
TS_ASSERT(!x);
|
||||
}
|
||||
|
||||
void test_node_visits_child_nodes()
|
||||
{
|
||||
Node a(Node::NODE_UNDEFINED, "A");
|
||||
Node b(Node::NODE_UNDEFINED, "B");
|
||||
Node c(Node::NODE_UNDEFINED, "C");
|
||||
Edge e(Edge::EDGE_MEMBER, &a, &b);
|
||||
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
||||
|
||||
std::vector<Node*> children;
|
||||
a.forEachChildNode(
|
||||
[&children](Node* n)
|
||||
{
|
||||
return children.push_back(n);
|
||||
}
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(children.size(), 2);
|
||||
TS_ASSERT_EQUALS(children[0], &b);
|
||||
TS_ASSERT_EQUALS(children[1], &c);
|
||||
}
|
||||
|
||||
void test_graph_saves_nodes()
|
||||
{
|
||||
TestGraph graph;
|
||||
@@ -284,6 +342,42 @@ public:
|
||||
TS_ASSERT(graph.getNode("A::C"));
|
||||
}
|
||||
|
||||
void test_node_in_graph_finds_child_node()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a = graph.createNodeHierarchy("A");
|
||||
Node* b = graph.createNodeHierarchy("A::B");
|
||||
Node* c = graph.createNodeHierarchy("A::C");
|
||||
|
||||
Node* x = a->findChildNode(
|
||||
[](Node* n)
|
||||
{
|
||||
return n->getName() == "C";
|
||||
}
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(x, c);
|
||||
TS_ASSERT_DIFFERS(x, b);
|
||||
}
|
||||
|
||||
void test_graph_saves_nodes_with_distinct_signatures()
|
||||
{
|
||||
TestGraph graph;
|
||||
Node* a1 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_FUNCTION, "A", "A1");
|
||||
Node* a2 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_FUNCTION, "A", "A2");
|
||||
Node* a3 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_FUNCTION, "A", "A2");
|
||||
|
||||
TS_ASSERT_DIFFERS(a1, a2);
|
||||
TS_ASSERT_EQUALS(a2, a3);
|
||||
|
||||
Node* c1 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_METHOD, "B::C", "C1");
|
||||
Node* c2 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_METHOD, "B::C", "C2");
|
||||
Node* c3 = graph.createNodeHierarchyWithDistinctSignature(Node::NODE_METHOD, "B::C", "C2");
|
||||
|
||||
TS_ASSERT_DIFFERS(c1, c2);
|
||||
TS_ASSERT_EQUALS(c2, c3);
|
||||
}
|
||||
|
||||
void test_graph_creates_multiple_nodes_as_undefined_nodes()
|
||||
{
|
||||
TestGraph graph;
|
||||
@@ -295,11 +389,11 @@ public:
|
||||
TS_ASSERT_EQUALS("A", graph.getNode("A")->getName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A")->getType());
|
||||
|
||||
TS_ASSERT_EQUALS("A::B", graph.getNode("A::B")->getName());
|
||||
TS_ASSERT_EQUALS("A::B", graph.getNode("A::B")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B")->getType());
|
||||
|
||||
TS_ASSERT_EQUALS(abc, graph.getNode("A::B::C"));
|
||||
TS_ASSERT_EQUALS("A::B::C", graph.getNode("A::B::C")->getName());
|
||||
TS_ASSERT_EQUALS("A::B::C", graph.getNode("A::B::C")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B::C")->getType());
|
||||
|
||||
Node* abcde = graph.createNodeHierarchy("A::B::C::D::E");
|
||||
@@ -307,11 +401,11 @@ public:
|
||||
TS_ASSERT_EQUALS(5, graph.getNodeCount());
|
||||
TS_ASSERT_EQUALS(4, graph.getEdgeCount());
|
||||
|
||||
TS_ASSERT_EQUALS("A::B::C::D", graph.getNode("A::B::C::D")->getName());
|
||||
TS_ASSERT_EQUALS("A::B::C::D", graph.getNode("A::B::C::D")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B::C::D")->getType());
|
||||
|
||||
TS_ASSERT_EQUALS(abcde, graph.getNode("A::B::C::D::E"));
|
||||
TS_ASSERT_EQUALS("A::B::C::D::E", graph.getNode("A::B::C::D::E")->getName());
|
||||
TS_ASSERT_EQUALS("A::B::C::D::E", graph.getNode("A::B::C::D::E")->getFullName());
|
||||
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B::C::D::E")->getType());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user