From b110d528dcb319cdb66fc071c263835c5451690b Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Thu, 31 Jul 2014 15:07:18 +0200 Subject: [PATCH] data: Added type bitmasking to Node and Edge and check type on Edge creation --- bin/test/data/log/test_log.txt | 1 + src/lib/data/graph/Edge.cpp | 88 +++++++++++++++++++++++++++++++++- src/lib/data/graph/Edge.h | 25 ++++++---- src/lib/data/graph/Node.cpp | 28 +++++++---- src/lib/data/graph/Node.h | 27 ++++++----- src/test/GraphTestSuite.h | 17 +++++++ 6 files changed, 153 insertions(+), 33 deletions(-) diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index e4f5dfca..57a99372 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -3,6 +3,7 @@ Token.cpp ERROR: Location Id was not referenced by this Token. Node.cpp WARNING: Cannot change 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. +Edge.cpp ERROR: Edge call can't go from Node undefined to Node undefined Settings.cpp WARNING: File for Settings not found. ConfigManager.cpp ERROR: value Bool is not present in config. ConfigManager.cpp ERROR: value Int is not present in config. diff --git a/src/lib/data/graph/Edge.cpp b/src/lib/data/graph/Edge.cpp index d60055ec..7d11ccf2 100644 --- a/src/lib/data/graph/Edge.cpp +++ b/src/lib/data/graph/Edge.cpp @@ -14,6 +14,8 @@ Edge::Edge(EdgeType type, Node* from, Node* to) { m_from->addEdge(this); m_to->addEdge(this); + + checkType(); } Edge::Edge(const Edge& other, Node* from, Node* to) @@ -30,6 +32,8 @@ Edge::Edge(const Edge& other, Node* from, Node* to) { LOG_ERROR("Nodes are not plain copies."); } + + checkType(); } Edge::~Edge() @@ -43,6 +47,11 @@ Edge::EdgeType Edge::getType() const return m_type; } +bool Edge::isType(EdgeTypeMask mask) const +{ + return (m_type & mask) > 0; +} + Node* Edge::getFrom() const { return m_from; @@ -102,9 +111,9 @@ void Edge::addComponentDataType(std::shared_ptr componen } } -std::string Edge::getTypeString() const +std::string Edge::getTypeString(EdgeType type) const { - switch (m_type) + switch (type) { case EDGE_MEMBER: return "child"; @@ -128,6 +137,11 @@ std::string Edge::getTypeString() const return ""; } +std::string Edge::getTypeString() const +{ + return getTypeString(m_type); +} + std::string Edge::getAsString() const { std::stringstream str; @@ -147,3 +161,73 @@ std::ostream& operator<<(std::ostream& ostream, const Edge& edge) ostream << edge.getAsString(); return ostream; } + +bool Edge::checkType() const +{ + Node::NodeTypeMask typeMask = Node::NODE_UNDEFINED | Node::NODE_CLASS | Node::NODE_STRUCT | Node::NODE_ENUM | Node::NODE_TYPEDEF; + Node::NodeTypeMask variableMask = Node::NODE_UNDEFINED | Node::NODE_GLOBAL_VARIABLE | Node::NODE_FIELD; + Node::NodeTypeMask functionMask = Node::NODE_UNDEFINED_FUNCTION | Node::NODE_FUNCTION | Node::NODE_METHOD; + + switch (m_type) + { + case EDGE_MEMBER: + if (!m_from->isType(Node::NODE_UNDEFINED | Node::NODE_CLASS | Node::NODE_STRUCT | Node::NODE_NAMESPACE | Node::NODE_ENUM) || + (m_to->isType(Node::NODE_NAMESPACE) && !m_from->isType(Node::NODE_UNDEFINED | Node::NODE_NAMESPACE)) || + (m_from->isType(Node::NODE_ENUM) && !m_to->isType(Node::NODE_FIELD))) + { + break; + } + return true; + + case EDGE_TYPE_OF: + if (!m_from->isType(variableMask) || !m_to->isType(typeMask)) + { + break; + } + return true; + + case EDGE_RETURN_TYPE_OF: + case EDGE_PARAMETER_TYPE_OF: + case EDGE_TYPE_USAGE: + if (!m_from->isType(functionMask) || !m_to->isType(typeMask)) + { + break; + } + return true; + + case EDGE_INHERITANCE: + if (!m_from->isType(Node::NODE_CLASS) || !m_to->isType(Node::NODE_UNDEFINED | Node::NODE_CLASS)) + { + break; + } + return true; + + case EDGE_CALL: + if (!m_from->isType(variableMask | functionMask) || !m_to->isType(functionMask)) + { + break; + } + return true; + + case EDGE_USAGE: + if (!m_from->isType(functionMask) || !m_to->isType(variableMask)) + { + break; + } + return true; + + case EDGE_TYPEDEF_OF: + if (!m_from->isType(Node::NODE_TYPEDEF) || !m_to->isType(typeMask)) + { + break; + } + return true; + } + + LOG_ERROR_STREAM( + << "Edge " << getTypeString() + << " can't go from Node " << m_from->getTypeString() + << " to Node " << m_to->getTypeString() + ); + return false; +} diff --git a/src/lib/data/graph/Edge.h b/src/lib/data/graph/Edge.h index d200c873..6cd2e99c 100644 --- a/src/lib/data/graph/Edge.h +++ b/src/lib/data/graph/Edge.h @@ -13,17 +13,18 @@ class TokenComponentDataType; class Edge: public Token { public: - enum EdgeType + typedef int EdgeTypeMask; + enum EdgeType : EdgeTypeMask { - EDGE_MEMBER, - EDGE_TYPE_OF, - EDGE_RETURN_TYPE_OF, - EDGE_PARAMETER_TYPE_OF, - EDGE_TYPE_USAGE, - EDGE_USAGE, - EDGE_CALL, - EDGE_INHERITANCE, - EDGE_TYPEDEF_OF + EDGE_MEMBER = 0x1, + EDGE_TYPE_OF = 0x2, + EDGE_RETURN_TYPE_OF = 0x4, + EDGE_PARAMETER_TYPE_OF = 0x8, + EDGE_TYPE_USAGE = 0x10, + EDGE_USAGE = 0x20, + EDGE_CALL = 0x40, + EDGE_INHERITANCE = 0x80, + EDGE_TYPEDEF_OF = 0x100 }; Edge(EdgeType type, Node* from, Node* to); @@ -31,6 +32,7 @@ public: virtual ~Edge(); EdgeType getType() const; + bool isType(EdgeTypeMask mask) const; Node* getFrom() const; Node* getTo() const; @@ -46,12 +48,15 @@ public: void addComponentDataType(std::shared_ptr component); // Logging. + std::string getTypeString(EdgeType type) const; std::string getTypeString() const; std::string getAsString() const; private: void operator=(const Node&); + bool checkType() const; + const EdgeType m_type; Node* const m_from; diff --git a/src/lib/data/graph/Node.cpp b/src/lib/data/graph/Node.cpp index 37370604..b9da6ee2 100644 --- a/src/lib/data/graph/Node.cpp +++ b/src/lib/data/graph/Node.cpp @@ -31,16 +31,21 @@ Node::NodeType Node::getType() const void Node::setType(NodeType type) { - if (type != m_type && m_type != NODE_UNDEFINED && m_type != NODE_UNDEFINED_FUNCTION) + if (!isType(type | NODE_UNDEFINED | NODE_UNDEFINED_FUNCTION)) { LOG_WARNING( - "Cannot change NodeType after it was already set from " + getTypeString(m_type) + " to " + getTypeString(type) + "Cannot change NodeType after it was already set from " + getTypeString() + " to " + getTypeString(type) ); return; } m_type = type; } +bool Node::isType(NodeTypeMask mask) const +{ + return (m_type & mask) > 0; +} + const std::string& Node::getName() const { return m_name; @@ -197,9 +202,9 @@ void Node::addComponentConst(std::shared_ptr component) { LOG_ERROR("TokenComponentConst has been set before!"); } - else if (m_type != NODE_METHOD) + else if (!isType(NODE_METHOD)) { - LOG_ERROR("TokenComponentConst can't be set on node of type: " + getTypeString(m_type)); + LOG_ERROR("TokenComponentConst can't be set on node of type: " + getTypeString()); } else { @@ -213,9 +218,9 @@ void Node::addComponentStatic(std::shared_ptr component) { LOG_ERROR("TokenComponentStatic has been set before!"); } - else if (m_type != NODE_GLOBAL_VARIABLE && m_type != NODE_FIELD && m_type != NODE_FUNCTION && m_type != NODE_METHOD) + else if (!isType(NODE_GLOBAL_VARIABLE | NODE_FIELD | NODE_FUNCTION | NODE_METHOD)) { - LOG_ERROR("TokenComponentStatic can't be set on node of type: " + getTypeString(m_type)); + LOG_ERROR("TokenComponentStatic can't be set on node of type: " + getTypeString()); } else { @@ -229,9 +234,9 @@ void Node::addComponentSignature(std::shared_ptr compon { LOG_ERROR("TokenComponentSignature has been set before!"); } - else if (m_type != NODE_UNDEFINED_FUNCTION && m_type != NODE_FUNCTION && m_type != NODE_METHOD) + else if (!isType(NODE_UNDEFINED_FUNCTION | NODE_FUNCTION | NODE_METHOD)) { - LOG_ERROR("TokenComponentSignature can't be set on node of type: " + getTypeString(m_type)); + LOG_ERROR("TokenComponentSignature can't be set on node of type: " + getTypeString()); } else { @@ -269,10 +274,15 @@ std::string Node::getTypeString(NodeType type) const return ""; } +std::string Node::getTypeString() const +{ + return getTypeString(m_type); +} + std::string Node::getAsString() const { std::stringstream str; - str << "[" << getId() << "] " << getTypeString(m_type) << ": " << "\"" << getName() << "\""; + str << "[" << getId() << "] " << getTypeString() << ": " << "\"" << getName() << "\""; if (getComponent()) { diff --git a/src/lib/data/graph/Node.h b/src/lib/data/graph/Node.h index b99225ca..ac1ff85b 100644 --- a/src/lib/data/graph/Node.h +++ b/src/lib/data/graph/Node.h @@ -16,19 +16,20 @@ class TokenComponentSignature; class Node: public Token { public: - enum NodeType + typedef int NodeTypeMask; + enum NodeType : NodeTypeMask { - NODE_UNDEFINED, - NODE_UNDEFINED_FUNCTION, - NODE_CLASS, - NODE_STRUCT, - NODE_GLOBAL_VARIABLE, - NODE_FIELD, - NODE_FUNCTION, - NODE_METHOD, - NODE_NAMESPACE, - NODE_ENUM, - NODE_TYPEDEF + NODE_UNDEFINED = 0x1, + NODE_UNDEFINED_FUNCTION = 0x2, + NODE_CLASS = 0x4, + NODE_STRUCT = 0x8, + NODE_GLOBAL_VARIABLE = 0x10, + NODE_FIELD = 0x20, + NODE_FUNCTION = 0x40, + NODE_METHOD = 0x80, + NODE_NAMESPACE = 0x100, + NODE_ENUM = 0x200, + NODE_TYPEDEF = 0x400 }; Node(NodeType type, const std::string& name); @@ -37,6 +38,7 @@ public: NodeType getType() const; void setType(NodeType type); + bool isType(NodeTypeMask mask) const; const std::string& getName() const; std::string getFullName() const; @@ -69,6 +71,7 @@ public: // Logging. std::string getTypeString(NodeType type) const; + std::string getTypeString() const; std::string getAsString() const; private: diff --git a/src/test/GraphTestSuite.h b/src/test/GraphTestSuite.h index eb44855c..7f66da15 100644 --- a/src/test/GraphTestSuite.h +++ b/src/test/GraphTestSuite.h @@ -148,6 +148,13 @@ public: TS_ASSERT_EQUALS(n.getType(), n2.getType()); } + void test_node_type_bit_masking() + { + Node n(Node::NODE_NAMESPACE, "A"); + TS_ASSERT(n.isType(Node::NODE_FUNCTION | Node::NODE_NAMESPACE | Node::NODE_CLASS)); + TS_ASSERT(!n.isType(Node::NODE_FUNCTION | Node::NODE_METHOD | Node::NODE_CLASS)); + } + void test_get_type_of_edges() { Node a(Node::NODE_UNDEFINED, "A"); @@ -169,6 +176,16 @@ public: TS_ASSERT_EQUALS(e.getType(), e2.getType()); } + void test_edge_type_bit_masking() + { + Node a(Node::NODE_UNDEFINED, "A"); + Node b(Node::NODE_UNDEFINED, "B"); + Edge e(Edge::EDGE_TYPE_OF, &a, &b); + + TS_ASSERT(e.isType(Edge::EDGE_MEMBER | Edge::EDGE_CALL | Edge::EDGE_TYPE_OF)); + TS_ASSERT(!e.isType(Edge::EDGE_USAGE | Edge::EDGE_MEMBER | Edge::EDGE_CALL)); + } + void test_node_finds_child_node() { Node a(Node::NODE_UNDEFINED, "A");