data: Moved EdgeComponent system to Token and extended it to cover all type specific Edge and Token fields

This change moves the EdgeComponent system to Token and redefines them as TokenComponents.
* Performance tests on the side showed that using typeid() in getComponent() is faster than dynamically casting every
pointer.
* The hasComponent() method was deliberately left out in the implementation, because it used to look up the right
component and discard it again. This check for presence can also be achieved by just using getComponent().
* The method addComponent() is protected in Token, so that Node and Edge can guard which Component is set on which type
by implementing specific setters for each Component.
* The GraphTestSuite was extended to include tests for the Component implementation (and missing tests for locationIds
in Token and copying of Node and Edge were added).
This commit is contained in:
Eberhard Graether
2014-07-26 02:26:59 +02:00
parent 4262be133a
commit 641acc2bde
29 changed files with 711 additions and 443 deletions
+3
View File
@@ -1,4 +1,7 @@
ConfigManager.cpp ERROR: value path/to/nowhere is not present in config.
Token.cpp ERROR: Location Id was not referenced by this Token.
Node.cpp WARNING: Changing NodeType after it was already set, from namespace to class
Edge.cpp ERROR: Nodes are not plain copies.
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
TextAccess.cpp WARNING: Index 'firstLine' has to be lower or equal index 'lastLine', is 3 > 2
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
+12 -4
View File
@@ -71,10 +71,18 @@ add_files(
data/access/GraphAccessProxy.cpp
data/access/GraphAccessProxy.h
data/graph/edgeComponent/EdgeComponent.cpp
data/graph/edgeComponent/EdgeComponent.h
data/graph/edgeComponent/EdgeComponentDataType.cpp
data/graph/edgeComponent/EdgeComponentDataType.h
data/graph/token_component/TokenComponent.cpp
data/graph/token_component/TokenComponent.h
data/graph/token_component/TokenComponentAccess.cpp
data/graph/token_component/TokenComponentAccess.h
data/graph/token_component/TokenComponentConst.cpp
data/graph/token_component/TokenComponentConst.h
data/graph/token_component/TokenComponentDataType.cpp
data/graph/token_component/TokenComponentDataType.h
data/graph/token_component/TokenComponentSignature.cpp
data/graph/token_component/TokenComponentSignature.h
data/graph/token_component/TokenComponentStatic.cpp
data/graph/token_component/TokenComponentStatic.h
data/graph/Edge.cpp
data/graph/Edge.h
+66 -52
View File
@@ -1,6 +1,8 @@
#include "data/Storage.h"
#include "data/graph/edgeComponent/EdgeComponentDataType.h"
#include "data/graph/token_component/TokenComponentConst.h"
#include "data/graph/token_component/TokenComponentDataType.h"
#include "data/graph/token_component/TokenComponentStatic.h"
#include "data/location/TokenLocation.h"
#include "data/location/TokenLocationFile.h"
#include "data/location/TokenLocationLine.h"
@@ -41,12 +43,9 @@ void Storage::onTypedefParsed(
){
log("typedef", fullName + " -> " + underlyingType.getFullTypeName(), location);
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_TYPEDEF);
node->setAccess(convertAccessType(access));
Node* node = m_graph.createNodeHierarchy(Node::NODE_TYPEDEF, fullName);
addAccess(node, access);
addTokenLocation(node, location);
addTypeEdge(node, Edge::EDGE_TYPEDEF_OF, underlyingType);
}
@@ -54,10 +53,8 @@ void Storage::onClassParsed(const ParseLocation& location, const std::string& fu
{
log("class", fullName, location);
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_CLASS);
node->setAccess(convertAccessType(access));
Node* node = m_graph.createNodeHierarchy(Node::NODE_CLASS, fullName);
addAccess(node, access);
addTokenLocation(node, location);
}
@@ -65,10 +62,8 @@ void Storage::onStructParsed(const ParseLocation& location, const std::string& f
{
log("struct", fullName, location);
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_STRUCT);
node->setAccess(convertAccessType(access));
Node* node = m_graph.createNodeHierarchy(Node::NODE_STRUCT, fullName);
addAccess(node, access);
addTokenLocation(node, location);
}
@@ -76,12 +71,14 @@ void Storage::onGlobalVariableParsed(const ParseLocation& location, const ParseV
{
log("global", variable.fullName, location);
Node* node = m_graph.createNodeHierarchy(variable.fullName);
node->setType(Node::NODE_GLOBAL_VARIABLE);
node->setStatic(variable.isStatic);
Node* node = m_graph.createNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, variable.fullName);
if (variable.isStatic)
{
node->addComponentStatic(std::make_shared<TokenComponentStatic>());
}
addTypeEdge(node, Edge::EDGE_TYPE_OF, variable.type);
addTokenLocation(node, location);
}
@@ -89,19 +86,21 @@ void Storage::onFieldParsed(const ParseLocation& location, const ParseVariable&
{
log("field", variable.fullName, location);
Node* node = m_graph.createNodeHierarchy(variable.fullName);
node->setType(Node::NODE_FIELD);
node->setStatic(variable.isStatic);
Node* node = m_graph.createNodeHierarchy(Node::NODE_FIELD, variable.fullName);
if (variable.isStatic)
{
node->addComponentStatic(std::make_shared<TokenComponentStatic>());
}
if (access == ACCESS_NONE)
{
LOG_ERROR("Field needs to have access type [public, protected, private] but has none.");
return;
}
node->setAccess(convertAccessType(access));
addAccess(node, access);
addTypeEdge(node, Edge::EDGE_TYPE_OF, variable.type);
addTokenLocation(node, location);
}
@@ -113,11 +112,9 @@ void Storage::onFunctionParsed(
log("function", fullName, location);
Node* node = m_graph.createNodeHierarchyWithDistinctSignature(
fullName,
Node::NODE_FUNCTION, fullName,
ParserClient::functionSignatureStr(returnType.type, fullName, parameters, false)
);
node->setType(Node::NODE_FUNCTION);
addTokenLocation(node, location);
addTypeEdge(node, Edge::EDGE_RETURN_TYPE_OF, returnType);
@@ -136,20 +133,26 @@ void Storage::onMethodParsed(
log("method", fullName, location);
Node* node = m_graph.createNodeHierarchyWithDistinctSignature(
fullName,
Node::NODE_METHOD, fullName,
ParserClient::functionSignatureStr(returnType.type, fullName, parameters, isConst)
);
node->setType(Node::NODE_METHOD);
node->setConst(isConst);
node->setStatic(isStatic);
if (isConst)
{
node->addComponentConst(std::make_shared<TokenComponentConst>());
}
if (isStatic)
{
node->addComponentStatic(std::make_shared<TokenComponentStatic>());
}
if (access == ACCESS_NONE)
{
LOG_ERROR("Method needs to have access type [public, protected, private] but has none.");
return;
}
node->setAccess(convertAccessType(access));
addAccess(node, access);
addTokenLocation(node, location);
@@ -164,9 +167,7 @@ void Storage::onNamespaceParsed(const ParseLocation& location, const std::string
{
log("namespace", fullName, location);
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_NAMESPACE);
Node* node = m_graph.createNodeHierarchy(Node::NODE_NAMESPACE, fullName);
addTokenLocation(node, location);
}
@@ -174,10 +175,8 @@ void Storage::onEnumParsed(const ParseLocation& location, const std::string& ful
{
log("enum", fullName, location);
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_ENUM);
node->setAccess(convertAccessType(access));
Node* node = m_graph.createNodeHierarchy(Node::NODE_ENUM, fullName);
addAccess(node, access);
addTokenLocation(node, location);
}
@@ -185,9 +184,7 @@ void Storage::onEnumFieldParsed(const ParseLocation& location, const std::string
{
log("enum field", fullName, location);
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_FIELD);
Node* node = m_graph.createNodeHierarchy(Node::NODE_FIELD, fullName);
addTokenLocation(node, location);
}
@@ -200,7 +197,7 @@ void Storage::onInheritanceParsed(
Node* baseNode = m_graph.createNodeHierarchy(baseName);
Edge* edge = m_graph.createEdge(Edge::EDGE_INHERITANCE, node, baseNode);
edge->setAccess(convertAccessType(access));
edge->addComponentAccess(std::make_shared<TokenComponentAccess>(convertAccessType(access)));
addTokenLocation(edge, location);
}
@@ -448,26 +445,46 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile(
return ret;
}
Edge::AccessType Storage::convertAccessType(ParserClient::AccessType access) const
TokenComponentAccess::AccessType Storage::convertAccessType(ParserClient::AccessType access) const
{
switch (access)
{
case ACCESS_PUBLIC:
return Edge::ACCESS_PUBLIC;
return TokenComponentAccess::ACCESS_PUBLIC;
case ACCESS_PROTECTED:
return Edge::ACCESS_PROTECTED;
return TokenComponentAccess::ACCESS_PROTECTED;
case ACCESS_PRIVATE:
return Edge::ACCESS_PRIVATE;
return TokenComponentAccess::ACCESS_PRIVATE;
case ACCESS_NONE:
return Edge::ACCESS_NONE;
return TokenComponentAccess::ACCESS_NONE;
}
}
TokenComponentAccess* Storage::addAccess(Node* node, ParserClient::AccessType access)
{
if (access != ACCESS_NONE)
{
std::shared_ptr<TokenComponentAccess> ptr = std::make_shared<TokenComponentAccess>(convertAccessType(access));
node->getMemberEdge()->addComponentAccess(ptr);
return ptr.get();
}
return nullptr;
}
Edge* Storage::addTypeEdge(Node* node, Edge::EdgeType edgeType, const DataType& type)
{
Node* typeNode = m_graph.createNodeHierarchy(type.getRawTypeName());
Edge* edge = m_graph.createEdge(edgeType, node, typeNode);
edge->addComponent(std::make_shared<EdgeComponentDataType>(type.getQualifierList(), type.getModifierStack()));
// FIXME: When a function uses the same type multiple times then we still only use one edge to save this,
// but we can't store multiple DataTypes on this edge at the moment.
if (!edge->getComponent<TokenComponentDataType>())
{
edge->addComponentDataType(
std::make_shared<TokenComponentDataType>(type.getQualifierList(), type.getModifierStack())
);
}
return edge;
}
@@ -478,10 +495,7 @@ Edge* Storage::addTypeEdge(Node* node, Edge::EdgeType edgeType, const ParseTypeU
return nullptr;
}
const DataType& type = typeUsage.type;
Node* typeNode = m_graph.createNodeHierarchy(type.getRawTypeName());
Edge* edge = m_graph.createEdge(edgeType, node, typeNode);
edge->addComponent(std::make_shared<EdgeComponentDataType>(type.getQualifierList(), type.getModifierStack()));
Edge* edge = addTypeEdge(node, edgeType, typeUsage.type);
addTokenLocation(edge, typeUsage.location);
return edge;
+3 -1
View File
@@ -7,6 +7,7 @@
#include "data/access/GraphAccess.h"
#include "data/access/LocationAccess.h"
#include "data/graph/Graph.h"
#include "data/graph/token_component/TokenComponentAccess.h"
#include "data/location/TokenLocationCollection.h"
#include "data/parser/ParserClient.h"
@@ -87,7 +88,8 @@ public:
) const;
private:
Edge::AccessType convertAccessType(ParserClient::AccessType access) const;
TokenComponentAccess::AccessType convertAccessType(ParserClient::AccessType access) const;
TokenComponentAccess* addAccess(Node* node, ParserClient::AccessType access);
Edge* addTypeEdge(Node* node, Edge::EdgeType edgeType, const DataType& type);
Edge* addTypeEdge(Node* node, Edge::EdgeType edgeType, const ParseTypeUsage& typeUsage);
TokenLocation* addTokenLocation(Token* token, const ParseLocation& location);
+44 -67
View File
@@ -3,45 +3,41 @@
#include <sstream>
#include "data/graph/Node.h"
#include "data/graph/edgeComponent/EdgeComponent.h"
#include "data/graph/token_component/TokenComponentAccess.h"
#include "data/graph/token_component/TokenComponentDataType.h"
#include "utility/logging/logging.h"
Edge::Edge(EdgeType type, Node* from, Node* to)
: m_type(type)
, m_from(from)
, m_to(to)
, m_access(ACCESS_NONE)
{
m_from->addEdge(this);
m_to->addEdge(this);
}
Edge::Edge(const Edge& other, Node* from, Node* to)
: Token(other)
, m_type(other.m_type)
, m_from(from)
, m_to(to)
{
m_from->addEdge(this);
m_to->addEdge(this);
if (m_from == other.m_from || m_to == other.m_to ||
m_from->getId() != other.m_from->getId() || m_to->getId() != other.m_to->getId())
{
LOG_ERROR("Nodes are not plain copies.");
}
}
Edge::~Edge()
{
m_from->removeEdge(this);
m_to->removeEdge(this);
}
std::shared_ptr<Edge> Edge::createPlainCopy(Node* from, Node* to) const
{
if (from == m_from || to == m_to || from->getId() != m_from->getId() || to->getId() != m_to->getId())
{
LOG_ERROR("Nodes are not plain copies.");
return nullptr;
}
std::shared_ptr<Edge> edge(new Edge(getId(), m_type, from, to));
edge->setAccess(m_access);
for (std::shared_ptr<EdgeComponent> component: m_components)
{
edge->addComponent(component->copy());
}
return edge;
}
Edge::EdgeType Edge::getType() const
{
return m_type;
@@ -67,24 +63,37 @@ bool Edge::isEdge() const
return true;
}
Edge::AccessType Edge::getAccess() const
void Edge::addComponentAccess(std::shared_ptr<TokenComponentAccess> component)
{
return m_access;
if (getComponent<TokenComponentAccess>())
{
LOG_ERROR("TokenComponentAccess has been set before!");
}
else if (m_type != EDGE_MEMBER && m_type != EDGE_INHERITANCE)
{
LOG_ERROR("TokenComponentAccess can't be set on edge of type: " + getTypeString());
}
else
{
addComponent(component);
}
}
void Edge::setAccess(AccessType access)
void Edge::addComponentDataType(std::shared_ptr<TokenComponentDataType> component)
{
if (access != ACCESS_NONE && m_type != EDGE_MEMBER && m_type != EDGE_INHERITANCE)
if (getComponent<TokenComponentDataType>())
{
LOG_ERROR("Setting access on wrong edge type.");
return;
LOG_ERROR("TokenComponentDataType has been set before!");
}
if (m_access != ACCESS_NONE && access != m_access)
else if (m_type != EDGE_TYPEDEF_OF && m_type != EDGE_TYPE_OF
&& m_type != EDGE_RETURN_TYPE_OF && m_type != EDGE_PARAMETER_TYPE_OF)
{
LOG_WARNING("Different AccessType was already set before.");
LOG_ERROR("TokenComponentDataType can't be set on edge of type: " + getTypeString());
}
else
{
addComponent(component);
}
m_access = access;
}
std::string Edge::getTypeString() const
@@ -111,52 +120,20 @@ std::string Edge::getTypeString() const
return "";
}
std::string Edge::getAccessString() const
{
switch (m_access)
{
case ACCESS_PUBLIC:
return "public";
case ACCESS_PROTECTED:
return "protected";
case ACCESS_PRIVATE:
return "private";
case ACCESS_NONE:
return "";
}
return "";
}
std::string Edge::getAsString() const
{
std::stringstream str;
str << "[" << getId() << "] \"" << m_from->getName() << "\" " << getTypeString() << " \"" + m_to->getName() << "\"";
if (m_access != ACCESS_NONE)
TokenComponentAccess* component = getComponent<TokenComponentAccess>();
if (component)
{
str << " " << getAccessString();
str << " " << component->getAccessString();
}
return str.str();
}
void Edge::addComponent(std::shared_ptr<EdgeComponent> component)
{
m_components.push_back(component);
component->setEdge(this);
}
Edge::Edge(Id id, EdgeType type, Node* from, Node* to)
: Token(id)
, m_type(type)
, m_from(from)
, m_to(to)
, m_access(ACCESS_NONE)
{
m_from->addEdge(this);
m_to->addEdge(this);
}
std::ostream& operator<<(std::ostream& ostream, const Edge& edge)
{
ostream << edge.getAsString();
+7 -50
View File
@@ -7,7 +7,8 @@
#include "data/graph/Token.h"
class Node;
class EdgeComponent;
class TokenComponentAccess;
class TokenComponentDataType;
class Edge: public Token
{
@@ -24,19 +25,10 @@ public:
EDGE_TYPEDEF_OF
};
enum AccessType
{
ACCESS_PUBLIC,
ACCESS_PROTECTED,
ACCESS_PRIVATE,
ACCESS_NONE
};
Edge(EdgeType type, Node* from, Node* to);
Edge(const Edge& other, Node* from, Node* to);
virtual ~Edge();
std::shared_ptr<Edge> createPlainCopy(Node* from, Node* to) const;
EdgeType getType() const;
Node* getFrom() const;
@@ -46,58 +38,23 @@ public:
virtual bool isNode() const;
virtual bool isEdge() const;
// Additional field accessors for different EdgeTypes.
AccessType getAccess() const;
void setAccess(AccessType access);
// Component setters
void addComponentAccess(std::shared_ptr<TokenComponentAccess> component);
void addComponentDataType(std::shared_ptr<TokenComponentDataType> component);
// Logging.
std::string getTypeString() const;
std::string getAccessString() const;
std::string getAsString() const;
void addComponent(std::shared_ptr<EdgeComponent> component);
template <typename ComponentType>
std::shared_ptr<ComponentType> getComponent() const;
template <typename ComponentType>
bool hasComponent() const;
private:
// Constructor for plain copies.
Edge(Id id, EdgeType type, Node* from, Node* to);
void operator=(const Node&);
const EdgeType m_type;
Node* const m_from;
Node* const m_to;
// Additional fields for different EdgeTypes.
AccessType m_access;
std::vector<std::shared_ptr<EdgeComponent>> m_components;
};
template <typename ComponentType>
std::shared_ptr<ComponentType> Edge::getComponent() const
{
std::shared_ptr<ComponentType> component;
for (std::shared_ptr<EdgeComponent> c: m_components)
{
component = std::dynamic_pointer_cast<ComponentType>(c);
if (component)
break;
}
return component;
}
template <typename ComponentType>
bool Edge::hasComponent() const
{
return (getComponent<ComponentType>());
}
std::ostream& operator<<(std::ostream& ostream, const Edge& edge);
#endif // EDGE_H
+48 -21
View File
@@ -1,5 +1,6 @@
#include "data/graph/Graph.h"
#include "data/graph/token_component/TokenComponentSignature.h"
#include "utility/logging/logging.h"
#include "utility/utilityString.h"
@@ -65,33 +66,52 @@ Token* Graph::getTokenById(Id id) const
Node* Graph::createNodeHierarchy(const std::string& fullName)
{
Node* node = getNode(fullName);
if (node)
{
return node;
}
return insertNodeHierarchy(fullName);
return createNodeHierarchy(Node::NODE_UNDEFINED, fullName);
}
Node* Graph::createNodeHierarchyWithDistinctSignature(const std::string& fullName, const std::string& signature)
Node* Graph::createNodeHierarchy(Node::NodeType type, const std::string& fullName)
{
Node* node = getNode(fullName);
if (node)
{
if (node->getSignature() == signature)
if (type != Node::NODE_UNDEFINED)
{
node->setType(type);
}
return node;
}
return insertNodeHierarchy(type, fullName);
}
Node* Graph::createNodeHierarchyWithDistinctSignature(const std::string& fullName, const std::string& signature)
{
return createNodeHierarchyWithDistinctSignature(Node::NODE_UNDEFINED, fullName, signature);
}
Node* Graph::createNodeHierarchyWithDistinctSignature(
Node::NodeType type, const std::string& fullName, const std::string& signature
){
Node* node = getNode(fullName);
if (node)
{
if (node->getComponent<TokenComponentSignature>()->getSignature() == signature)
{
if (type != Node::NODE_UNDEFINED)
{
node->setType(type);
}
return node;
}
node = insertNode(fullName, node->getParentNode());
node = insertNode(type, fullName, node->getParentNode());
}
else
{
node = insertNodeHierarchy(fullName);
node = insertNodeHierarchy(type, fullName);
}
node->setSignature(signature);
node->addComponentSignature(std::make_shared<TokenComponentSignature>(signature));
return node;
}
@@ -268,7 +288,7 @@ Node* Graph::addNodeAsPlainCopy(Node* node)
return n;
}
std::shared_ptr<Node> copy = node->createPlainCopy();
std::shared_ptr<Node> copy = std::make_shared<Node>(*node);
m_nodes.push_back(copy);
return copy.get();
}
@@ -284,32 +304,39 @@ Edge* Graph::addEdgeAsPlainCopy(Edge* edge)
Node* from = addNodeAsPlainCopy(edge->getFrom());
Node* to = addNodeAsPlainCopy(edge->getTo());
std::shared_ptr<Edge> copy = edge->createPlainCopy(from, to);
std::shared_ptr<Edge> copy = std::make_shared<Edge>(*edge, from, to);
m_edges.push_back(copy);
return copy.get();
}
const std::string Graph::DELIMITER = "::";
Node* Graph::insertNodeHierarchy(const std::string& fullName)
Node* Graph::insertNodeHierarchy(Node::NodeType type, const std::string& fullName)
{
Node* node = nullptr;
std::vector<std::string> names = utility::split(fullName, DELIMITER);
std::string name;
for (std::vector<std::string>::iterator it = names.begin(); it != names.end(); it++)
for (size_t i = 0; i < names.size(); i++)
{
if (name.size() > 0)
if (i > 0)
{
name += DELIMITER;
}
name += *it;
name += names[i];
Node* childNode = getNode(name);
if (!childNode)
{
childNode = insertNode(name, node);
if (i == names.size() - 1)
{
childNode = insertNode(type, name, node);
}
else
{
childNode = insertNode(Node::NODE_UNDEFINED, name, node);
}
}
node = childNode;
@@ -318,9 +345,9 @@ Node* Graph::insertNodeHierarchy(const std::string& fullName)
return node;
}
Node* Graph::insertNode(const std::string& fullName, Node* parentNode)
Node* Graph::insertNode(Node::NodeType type, const std::string& fullName, Node* parentNode)
{
std::shared_ptr<Node> nodePtr = std::make_shared<Node>(Node::NODE_UNDEFINED, fullName);
std::shared_ptr<Node> nodePtr = std::make_shared<Node>(type, fullName);
m_nodes.push_back(nodePtr);
Node* node = nodePtr.get();
+8 -2
View File
@@ -22,7 +22,13 @@ public:
Token* getTokenById(Id id) const;
Node* createNodeHierarchy(const std::string& fullName);
Node* createNodeHierarchy(Node::NodeType type, const std::string& fullName);
Node* createNodeHierarchyWithDistinctSignature(const std::string& fullName, const std::string& signature);
Node* createNodeHierarchyWithDistinctSignature(
Node::NodeType type, const std::string& fullName, const std::string& signature
);
Edge* createEdge(Edge::EdgeType type, Node* from, Node* to);
void removeNode(Node* node);
@@ -48,8 +54,8 @@ protected:
private:
static const std::string DELIMITER;
Node* insertNodeHierarchy(const std::string& fullName);
Node* insertNode(const std::string& fullName, Node* parentNode);
Node* insertNodeHierarchy(Node::NodeType type, const std::string& fullName);
Node* insertNode(Node::NodeType type, const std::string& fullName, Node* parentNode);
Edge* insertEdge(Edge::EdgeType type, Node* from, Node* to);
void removeEdgeInternal(Edge* edge);
+44 -100
View File
@@ -2,13 +2,21 @@
#include <sstream>
#include "data/graph/token_component/TokenComponentConst.h"
#include "data/graph/token_component/TokenComponentStatic.h"
#include "data/graph/token_component/TokenComponentSignature.h"
#include "utility/logging/logging.h"
Node::Node(NodeType type, const std::string& name)
: m_type(type)
, m_name(name)
, m_isConst(false)
, m_isStatic(false)
{
}
Node::Node(const Node& other)
: Token(other)
, m_type(other.m_type)
, m_name(other.m_name)
{
}
@@ -16,16 +24,6 @@ Node::~Node()
{
}
std::shared_ptr<Node> Node::createPlainCopy() const
{
std::shared_ptr<Node> node(new Node(getId(), m_type, m_name));
node->setConst(m_isConst);
node->setStatic(m_isStatic);
return node;
}
Node::NodeType Node::getType() const
{
return m_type;
@@ -33,11 +31,12 @@ Node::NodeType Node::getType() const
void Node::setType(NodeType type)
{
if (type != m_type && m_type != NODE_NAMESPACE && m_type != NODE_UNDEFINED)
if (type != m_type && m_type != NODE_UNDEFINED)
{
LOG_WARNING(
"Changing NodeType after it was already set, from " + getTypeString(m_type) + " to " + getTypeString(type)
);
return;
}
m_type = type;
}
@@ -148,98 +147,52 @@ bool Node::isEdge() const
return false;
}
void Node::setAccess(Edge::AccessType access)
void Node::addComponentConst(std::shared_ptr<TokenComponentConst> component)
{
if (access != Edge::ACCESS_NONE)
if (getComponent<TokenComponentConst>())
{
if (!getMemberEdge())
{
LOG_WARNING("Can't set access on node " + getName() + ", because it is not a child.");
return;
}
getMemberEdge()->setAccess(access);
LOG_ERROR("TokenComponentConst has been set before!");
}
else if (m_type != NODE_METHOD)
{
LOG_ERROR("TokenComponentConst can't be set on node of type: " + getTypeString(m_type));
}
else
{
addComponent(component);
}
}
bool Node::isConst() const
void Node::addComponentStatic(std::shared_ptr<TokenComponentStatic> component)
{
return m_isConst;
}
void Node::setConst(bool isConst)
{
if (isConst && m_type != NODE_GLOBAL_VARIABLE && m_type != NODE_FIELD && m_type != NODE_METHOD)
if (getComponent<TokenComponentStatic>())
{
LOG_ERROR("Setting const on wrong node of type " + getTypeString(m_type));
return;
LOG_ERROR("TokenComponentStatic has been set before!");
}
m_isConst = isConst;
}
bool Node::isStatic() const
{
return m_isStatic;
}
void Node::setStatic(bool isStatic)
{
if (isStatic && m_type != NODE_GLOBAL_VARIABLE && m_type != NODE_FIELD && m_type != NODE_METHOD)
else if (m_type != NODE_GLOBAL_VARIABLE && m_type != NODE_FIELD && m_type != NODE_FUNCTION && m_type != NODE_METHOD)
{
LOG_ERROR("Setting static on wrong node of type " + getTypeString(m_type));
return;
LOG_ERROR("TokenComponentStatic can't be set on node of type: " + getTypeString(m_type));
}
else
{
addComponent(component);
}
m_isStatic = isStatic;
}
std::string Node::getSignature() const
void Node::addComponentSignature(std::shared_ptr<TokenComponentSignature> component)
{
// Signature generation from edges failed, because parameter edges to same type are bundled.
// std::string str;
// Edge* returnTypeEdge = findEdgeOfType(Edge::EDGE_RETURN_TYPE_OF);
// str += returnTypeEdge->getComponent<EdgeComponentDataType>()->getDataType().getFullTypeName() + " " + m_name + "(";
// forEachEdgeOfType(Edge::EDGE_PARAMETER_TYPE_OF,
// [&str](Edge* edge)
// {
// str += edge->getComponent<EdgeComponentDataType>()->getDataType().getFullTypeName() + ", ";
// }
// );
// if (*str.rbegin() == ' ')
// {
// str.pop_back();
// str.pop_back();
// }
// str += ")";
// if (isConst())
// {
// str += " const";
// }
// return str;
return m_signature;
}
void Node::setSignature(const std::string& signature)
{
if (m_type != NODE_FUNCTION && m_type != NODE_METHOD && m_type != NODE_UNDEFINED)
if (getComponent<TokenComponentSignature>())
{
LOG_ERROR("Signature is not supported on node of type " + getTypeString(m_type));
return;
LOG_ERROR("TokenComponentSignature has been set before!");
}
if (m_signature.size())
else if (m_type != NODE_FUNCTION && m_type != NODE_METHOD)
{
LOG_ERROR("Signature was already set before.");
return;
LOG_ERROR("TokenComponentSignature can't be set on node of type: " + getTypeString(m_type));
}
else
{
addComponent(component);
}
m_signature = signature;
}
std::string Node::getTypeString(NodeType type) const
@@ -247,7 +200,7 @@ std::string Node::getTypeString(NodeType type) const
switch (type)
{
case NODE_UNDEFINED:
return "type";
return "undefined";
case NODE_CLASS:
return "class";
case NODE_STRUCT:
@@ -275,12 +228,12 @@ std::string Node::getAsString() const
std::stringstream str;
str << "[" << getId() << "] " << getTypeString(m_type) << ": " << "\"" << getName() << "\"";
if (isStatic())
if (getComponent<TokenComponentStatic>())
{
str << " static";
}
if (isConst())
if (getComponent<TokenComponentConst>())
{
str << " const";
}
@@ -288,15 +241,6 @@ std::string Node::getAsString() const
return str.str();
}
Node::Node(Id id, NodeType type, const std::string& name)
: Token(id)
, m_type(type)
, m_name(name)
, m_isConst(false)
, m_isStatic(false)
{
}
std::ostream& operator<<(std::ostream& ostream, const Node& node)
{
ostream << node.getAsString();
+10 -21
View File
@@ -9,6 +9,10 @@
#include "data/graph/Edge.h"
#include "data/graph/Token.h"
class TokenComponentConst;
class TokenComponentStatic;
class TokenComponentSignature;
class Node: public Token
{
public:
@@ -27,10 +31,9 @@ public:
};
Node(NodeType type, const std::string& name);
Node(const Node& other);
virtual ~Node();
std::shared_ptr<Node> createPlainCopy() const;
NodeType getType() const;
void setType(NodeType type);
@@ -54,36 +57,22 @@ public:
virtual bool isNode() const;
virtual bool isEdge() const;
// Additional field accessors for different NodeTypes.
void setAccess(Edge::AccessType access);
bool isConst() const;
void setConst(bool isConst);
bool isStatic() const;
void setStatic(bool isStatic);
std::string getSignature() const;
void setSignature(const std::string& signature);
// Component setters.
void addComponentConst(std::shared_ptr<TokenComponentConst> component);
void addComponentStatic(std::shared_ptr<TokenComponentStatic> component);
void addComponentSignature(std::shared_ptr<TokenComponentSignature> component);
// Logging.
std::string getTypeString(NodeType type) const;
std::string getAsString() const;
private:
// Constructor for plain copies.
Node(Id id, NodeType type, const std::string& name);
void operator=(const Node&);
NodeType m_type;
std::string m_name;
std::vector<Edge*> m_edges;
// Additional fields for different NodeTypes.
bool m_isConst;
bool m_isStatic;
std::string m_signature;
};
std::ostream& operator<<(std::ostream& ostream, const Node& node);
+11 -2
View File
@@ -41,9 +41,18 @@ void Token::removeLocationId(Id locationId)
LOG_ERROR("Location Id was not referenced by this Token.");
}
Token::Token(Id id)
: m_id(id)
Token::Token(const Token& other)
: m_id(other.m_id)
{
for (std::shared_ptr<TokenComponent> component: other.m_components)
{
addComponent(component->copy());
}
}
void Token::addComponent(std::shared_ptr<TokenComponent> component)
{
m_components.push_back(component);
}
Id Token::s_nextId = 1;
+41 -3
View File
@@ -1,8 +1,10 @@
#ifndef TOKEN_H
#define TOKEN_H
#include <typeinfo>
#include <vector>
#include "data/graph/token_component/TokenComponent.h"
#include "utility/types.h"
class Token
@@ -21,19 +23,55 @@ public:
void addLocationId(Id locationId);
void removeLocationId(Id locationId);
template <typename ComponentType>
ComponentType* getComponent() const;
template <typename ComponentType>
std::shared_ptr<ComponentType> removeComponent();
protected:
// Constructor for plain copies of Node and Edge
Token(Id id);
Token(const Token& other);
void addComponent(std::shared_ptr<TokenComponent> component);
void copyComponentsFrom(const Token& other);
private:
static Id s_nextId;
Token(const Token&);
void operator=(const Token&);
const Id m_id; // own id
std::vector<Id> m_locationIds;
std::vector<std::shared_ptr<TokenComponent>> m_components;
};
template <typename ComponentType>
ComponentType* Token::getComponent() const
{
for (std::shared_ptr<TokenComponent> component: m_components)
{
if (typeid(ComponentType) == typeid(*(component.get())))
{
return dynamic_cast<ComponentType*>(component.get());
}
}
return nullptr;
}
template <typename ComponentType>
std::shared_ptr<ComponentType> Token::removeComponent()
{
for (size_t i = 0; i < m_components.size(); i++)
{
std::shared_ptr<TokenComponent> component = m_components[i];
if (typeid(ComponentType) == typeid(*(component.get())))
{
m_components.erase(m_components.begin() + i);
return std::dynamic_pointer_cast<ComponentType>(component);
}
}
return nullptr;
}
#endif // TOKEN_H
@@ -1,19 +0,0 @@
#include "data/graph/edgeComponent/EdgeComponent.h"
EdgeComponent::EdgeComponent()
{
}
EdgeComponent::~EdgeComponent()
{
}
void EdgeComponent::setEdge(Edge* edge)
{
m_edge = edge;
}
Edge* EdgeComponent::getEdge() const
{
return m_edge;
}
@@ -1,23 +0,0 @@
#ifndef EDGE_COMPONENT_H
#define EDGE_COMPONENT_H
#include "data/graph/Edge.h"
class EdgeComponent
{
public:
EdgeComponent();
virtual ~EdgeComponent();
virtual std::shared_ptr<EdgeComponent> copy() const = 0;
void setEdge(Edge* edge);
protected:
Edge* getEdge() const;
private:
Edge* m_edge;
};
#endif // EDGE_COMPONENT_H
@@ -1,24 +0,0 @@
#include "data/graph/edgeComponent/EdgeComponentDataType.h"
#include "data/type/DataType.h"
#include "data/graph/Node.h"
EdgeComponentDataType::EdgeComponentDataType(const DataTypeQualifierList qualifierList, const DataTypeModifierStack modifierStack)
: m_qualifierList(qualifierList)
, m_modifierStack(modifierStack)
{
}
EdgeComponentDataType::~EdgeComponentDataType()
{
}
std::shared_ptr<EdgeComponent> EdgeComponentDataType::copy() const
{
return std::make_shared<EdgeComponentDataType>(m_qualifierList, m_modifierStack);
}
DataType EdgeComponentDataType::getDataType() const
{
return DataType(getEdge()->getTo()->getName(), m_qualifierList, m_modifierStack);
}
@@ -1,25 +0,0 @@
#ifndef EDGE_COMPONENT_DATA_TYPE_H
#define EDGE_COMPONENT_DATA_TYPE_H
#include "data/graph/edgeComponent/EdgeComponent.h"
#include "data/type/DataTypeModifierStack.h"
#include "data/type/DataTypeQualifierList.h"
class DataType;
class EdgeComponentDataType: public EdgeComponent
{
public:
EdgeComponentDataType(const DataTypeQualifierList qualifierList, const DataTypeModifierStack modifierStack);
virtual ~EdgeComponentDataType();
virtual std::shared_ptr<EdgeComponent> copy() const;
DataType getDataType() const;
private:
const DataTypeQualifierList m_qualifierList;
const DataTypeModifierStack m_modifierStack;
};
#endif // EDGE_COMPONENT_DATA_TYPE_H
@@ -0,0 +1,5 @@
#include "data/graph/token_component/TokenComponent.h"
TokenComponent::~TokenComponent()
{
}
@@ -0,0 +1,13 @@
#ifndef TOKEN_COMPONENT_H
#define TOKEN_COMPONENT_H
#include <memory>
class TokenComponent
{
public:
virtual ~TokenComponent();
virtual std::shared_ptr<TokenComponent> copy() const = 0;
};
#endif // TOKEN_COMPONENT_H
@@ -0,0 +1,36 @@
#include "data/graph/token_component/TokenComponentAccess.h"
TokenComponentAccess::TokenComponentAccess(AccessType access)
: m_access(access)
{
}
TokenComponentAccess::~TokenComponentAccess()
{
}
std::shared_ptr<TokenComponent> TokenComponentAccess::copy() const
{
return std::make_shared<TokenComponentAccess>(*this);
}
TokenComponentAccess::AccessType TokenComponentAccess::getAccess() const
{
return m_access;
}
std::string TokenComponentAccess::getAccessString() const
{
switch (m_access)
{
case ACCESS_PUBLIC:
return "public";
case ACCESS_PROTECTED:
return "protected";
case ACCESS_PRIVATE:
return "private";
case ACCESS_NONE:
return "";
}
return "";
}
@@ -0,0 +1,33 @@
#ifndef TOKEN_COMPONENT_ACCESS
#define TOKEN_COMPONENT_ACCESS
#include <string>
#include "data/graph/token_component/TokenComponent.h"
class TokenComponentAccess
: public TokenComponent
{
public:
enum AccessType
{
ACCESS_PUBLIC,
ACCESS_PROTECTED,
ACCESS_PRIVATE,
ACCESS_NONE
};
TokenComponentAccess(AccessType access);
virtual ~TokenComponentAccess();
virtual std::shared_ptr<TokenComponent> copy() const;
AccessType getAccess() const;
std::string getAccessString() const;
private:
const AccessType m_access;
};
#endif // TOKEN_COMPONENT_ACCESS
@@ -0,0 +1,6 @@
#include "data/graph/token_component/TokenComponentConst.h"
std::shared_ptr<TokenComponent> TokenComponentConst::copy() const
{
return std::make_shared<TokenComponentConst>(*this);
}
@@ -0,0 +1,13 @@
#ifndef TOKEN_COMPONENT_CONST
#define TOKEN_COMPONENT_CONST
#include "data/graph/token_component/TokenComponent.h"
class TokenComponentConst
: public TokenComponent
{
public:
virtual std::shared_ptr<TokenComponent> copy() const;
};
#endif // TOKEN_COMPONENT_CONST
@@ -0,0 +1,30 @@
#include "data/graph/token_component/TokenComponentDataType.h"
#include "data/type/DataType.h"
TokenComponentDataType::TokenComponentDataType(
const DataTypeQualifierList qualifierList, const DataTypeModifierStack modifierStack
)
: m_qualifierList(qualifierList)
, m_modifierStack(modifierStack)
{
}
TokenComponentDataType::~TokenComponentDataType()
{
}
std::shared_ptr<TokenComponent> TokenComponentDataType::copy() const
{
return std::make_shared<TokenComponentDataType>(*this);
}
DataType TokenComponentDataType::getDataType(const std::string& typeName) const
{
return DataType(typeName, m_qualifierList, m_modifierStack);
}
std::string TokenComponentDataType::getQualifiedTypeName(const std::string& typeName) const
{
return m_modifierStack.applyTo(m_qualifierList.applyTo(typeName));
}
@@ -0,0 +1,27 @@
#ifndef TOKEN_COMPONENT_DATA_TYPE
#define TOKEN_COMPONENT_DATA_TYPE
#include "data/graph/token_component/TokenComponent.h"
#include "data/type/DataTypeModifierStack.h"
#include "data/type/DataTypeQualifierList.h"
class DataType;
class TokenComponentDataType
: public TokenComponent
{
public:
TokenComponentDataType(const DataTypeQualifierList qualifierList, const DataTypeModifierStack modifierStack);
virtual ~TokenComponentDataType();
virtual std::shared_ptr<TokenComponent> copy() const;
DataType getDataType(const std::string& typeName) const;
std::string getQualifiedTypeName(const std::string& typeName) const;
private:
const DataTypeQualifierList m_qualifierList;
const DataTypeModifierStack m_modifierStack;
};
#endif // TOKEN_COMPONENT_DATA_TYPE
@@ -0,0 +1,20 @@
#include "data/graph/token_component/TokenComponentSignature.h"
TokenComponentSignature::TokenComponentSignature(std::string signature)
: m_signature(signature)
{
}
TokenComponentSignature::~TokenComponentSignature()
{
}
std::shared_ptr<TokenComponent> TokenComponentSignature::copy() const
{
return std::make_shared<TokenComponentSignature>(*this);
}
const std::string& TokenComponentSignature::getSignature() const
{
return m_signature;
}
@@ -0,0 +1,23 @@
#ifndef TOKEN_COMPONENT_SIGNATURE
#define TOKEN_COMPONENT_SIGNATURE
#include <string>
#include "data/graph/token_component/TokenComponent.h"
class TokenComponentSignature
: public TokenComponent
{
public:
TokenComponentSignature(std::string signature);
virtual ~TokenComponentSignature();
virtual std::shared_ptr<TokenComponent> copy() const;
const std::string& getSignature() const;
private:
const std::string m_signature;
};
#endif // TOKEN_COMPONENT_SIGNATURE
@@ -0,0 +1,6 @@
#include "data/graph/token_component/TokenComponentStatic.h"
std::shared_ptr<TokenComponent> TokenComponentStatic::copy() const
{
return std::make_shared<TokenComponentStatic>(*this);
}
@@ -0,0 +1,13 @@
#ifndef TOKEN_COMPONENT_STATIC
#define TOKEN_COMPONENT_STATIC
#include "data/graph/token_component/TokenComponent.h"
class TokenComponentStatic
: public TokenComponent
{
public:
virtual std::shared_ptr<TokenComponent> copy() const;
};
#endif // TOKEN_COMPONENT_STATIC
+189 -29
View File
@@ -1,32 +1,153 @@
#include "cxxtest/TestSuite.h"
#include "data/graph/Graph.h"
#include "data/graph/edgeComponent/EdgeComponentDataType.h"
#include "data/type/modifier/DataTypeModifierPointer.h"
class GraphTestSuite : public CxxTest::TestSuite
{
public:
void test_tokens_get_unique_id()
{
Node a(Node::NODE_UNDEFINED, "A");
Node b(Node::NODE_UNDEFINED, "B");
Node c(Node::NODE_UNDEFINED, "C");
TestToken a;
TestToken b;
TestToken c;
TS_ASSERT_DIFFERS(a.getId(), c.getId());
TS_ASSERT_DIFFERS(a.getId(), b.getId());
TS_ASSERT_DIFFERS(b.getId(), c.getId());
}
void test_get_and_set_type_of_nodes()
void test_tokens_save_location_ids()
{
Node n(Node::NODE_NAMESPACE, "A");
TS_ASSERT_EQUALS(Node::NODE_NAMESPACE, n.getType());
TestToken a;
a.addLocationId(23);
a.addLocationId(5);
TS_ASSERT_EQUALS(a.getLocationIds().size(), 2);
TS_ASSERT_EQUALS(a.getLocationIds()[0], 23);
TS_ASSERT_EQUALS(a.getLocationIds()[1], 5);
}
void test_tokens_remove_location_ids()
{
TestToken a;
a.addLocationId(23);
a.addLocationId(5);
a.removeLocationId(42);
a.removeLocationId(5);
TS_ASSERT_EQUALS(a.getLocationIds().size(), 1);
TS_ASSERT_EQUALS(a.getLocationIds()[0], 23);
}
void test_token_saves_component()
{
TestToken a;
std::shared_ptr<TestComponent> component = std::make_shared<TestComponent>();
a.addComponent(component);
TS_ASSERT(a.getComponent<TestComponent>());
TS_ASSERT(!a.getComponent<Test2Component>());
TS_ASSERT_EQUALS(a.getComponent<TestComponent>(), component.get());
}
void test_token_saves_multiple_components()
{
TestToken a;
std::shared_ptr<TestComponent> component = std::make_shared<TestComponent>();
std::shared_ptr<Test2Component> component2 = std::make_shared<Test2Component>();
a.addComponent(component2);
a.addComponent(component);
TS_ASSERT(a.getComponent<TestComponent>());
TS_ASSERT(a.getComponent<Test2Component>());
TS_ASSERT_EQUALS(a.getComponent<TestComponent>(), component.get());
TS_ASSERT_EQUALS(a.getComponent<Test2Component>(), component2.get());
}
void test_token_removes_component()
{
TestToken a;
std::shared_ptr<TestComponent> component = std::make_shared<TestComponent>();
std::shared_ptr<Test2Component> component2 = std::make_shared<Test2Component>();
a.addComponent(component2);
a.addComponent(component);
std::shared_ptr<TestComponent> component3 = a.removeComponent<TestComponent>();
TS_ASSERT(!a.getComponent<TestComponent>());
TS_ASSERT(a.getComponent<Test2Component>());
TS_ASSERT_EQUALS(component3.get(), component.get());
TS_ASSERT_EQUALS(a.getComponent<Test2Component>(), component2.get());
}
void test_token_copies_components_when_token_is_copied()
{
TestToken a;
std::shared_ptr<TestComponent> component = std::make_shared<TestComponent>();
std::shared_ptr<Test2Component> component2 = std::make_shared<Test2Component>();
a.addComponent(component2);
a.addComponent(component);
TestToken b(a);
TS_ASSERT(b.getComponent<TestComponent>());
TS_ASSERT(b.getComponent<Test2Component>());
TS_ASSERT_DIFFERS(b.getComponent<TestComponent>(), component.get());
TS_ASSERT_DIFFERS(b.getComponent<Test2Component>(), component2.get());
}
void test_nodes_are_nodes()
{
Node a(Node::NODE_UNDEFINED, "A");
TS_ASSERT(a.isNode());
TS_ASSERT(!a.isEdge());
}
void test_edges_are_edges()
{
Node a(Node::NODE_UNDEFINED, "A");
Node b(Node::NODE_UNDEFINED, "B");
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
TS_ASSERT(!e.isNode());
TS_ASSERT(e.isEdge());
}
void test_set_type_of_node_from_constructor()
{
Node n(Node::NODE_FUNCTION, "A");
TS_ASSERT_EQUALS(Node::NODE_FUNCTION, n.getType());
}
void test_set_type_of_node_from_undefined()
{
Node n(Node::NODE_UNDEFINED, "A");
n.setType(Node::NODE_CLASS);
TS_ASSERT_EQUALS(Node::NODE_CLASS, n.getType());
}
void test_can_not_change_type_of_node_after_it_was_set()
{
Node n(Node::NODE_NAMESPACE, "A");
n.setType(Node::NODE_CLASS);
TS_ASSERT_DIFFERS(Node::NODE_CLASS, n.getType());
}
void test_node_can_be_copied_and_keeps_same_id()
{
Node n(Node::NODE_NAMESPACE, "A");
Node n2(n);
TS_ASSERT_DIFFERS(&n, &n2);
TS_ASSERT_EQUALS(n.getId(), n2.getId());
TS_ASSERT_EQUALS(n.getName(), n2.getName());
TS_ASSERT_EQUALS(n.getType(), n2.getType());
}
void test_get_type_of_edges()
{
Node a(Node::NODE_UNDEFINED, "A");
@@ -36,19 +157,16 @@ public:
TS_ASSERT_EQUALS(Edge::EDGE_TYPE_OF, e.getType());
}
void test_get_and_set_const_and_static_of_nodes()
void test_edge_can_be_copied_and_keeps_same_id()
{
Node n(Node::NODE_GLOBAL_VARIABLE, "A");
TS_ASSERT(!n.isConst());
TS_ASSERT(!n.isStatic());
Node a(Node::NODE_UNDEFINED, "A");
Node b(Node::NODE_UNDEFINED, "B");
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
Edge e2(e, &a, &b);
n.setConst(true);
TS_ASSERT(n.isConst());
TS_ASSERT(!n.isStatic());
n.setStatic(true);
TS_ASSERT(n.isConst());
TS_ASSERT(n.isStatic());
TS_ASSERT_DIFFERS(&e, &e2);
TS_ASSERT_EQUALS(e.getId(), e2.getId());
TS_ASSERT_EQUALS(e.getType(), e2.getType());
}
void test_graph_saves_nodes()
@@ -197,14 +315,6 @@ public:
TS_ASSERT_EQUALS(Node::NODE_UNDEFINED, graph.getNode("A::B::C::D::E")->getType());
}
void test_set_access_on_child_edge_via_node()
{
TestGraph graph;
Node* b = graph.createNodeHierarchy("A::B");
b->getMemberEdge()->setAccess(Edge::ACCESS_PRIVATE);
TS_ASSERT_EQUALS(Edge::ACCESS_PRIVATE, b->getMemberEdge()->getAccess());
}
void test_visit_each_token_on_graph()
{
TestGraph graph;
@@ -251,7 +361,6 @@ public:
{
TestGraph graph;
Node* b = graph.createNodeHierarchy("A::B");
b->getMemberEdge()->setAccess(Edge::ACCESS_PUBLIC);
graph.createNodeHierarchy("A::B::C");
Node* d = graph.createNodeHierarchy("D");
Node* e = graph.createNodeHierarchy("E");
@@ -279,10 +388,61 @@ public:
TS_ASSERT(plainGraph.getNode("A::B::C"));
TS_ASSERT(plainGraph.getNode("D"));
TS_ASSERT(!plainGraph.getNode("E"));
TS_ASSERT_EQUALS(Edge::ACCESS_PUBLIC, plainGraph.getNode("A::B")->getMemberEdge()->getAccess());
}
private:
class TestToken: public Token
{
public:
TestToken()
{
}
TestToken(const TestToken& other)
: Token(other)
{
}
virtual bool isNode() const
{
return false;
}
virtual bool isEdge() const
{
return false;
}
void addComponent(std::shared_ptr<TokenComponent> component)
{
Token::addComponent(component);
}
template<typename ComponentType>
std::shared_ptr<ComponentType> removeComponent()
{
return Token::removeComponent<ComponentType>();
}
};
class TestComponent: public TokenComponent
{
public:
virtual std::shared_ptr<TokenComponent> copy() const
{
return std::make_shared<TestComponent>(*this);
}
};
class Test2Component: public TokenComponent
{
public:
virtual std::shared_ptr<TokenComponent> copy() const
{
return std::make_shared<Test2Component>(*this);
}
};
class TestGraph: public Graph
{
public: