logic: added query syntax and filtering system for search
This change allows the user to use a simple query syntax in the search field to filter the results using names,
operators and predefined filters.
The class QueryTree is capable of parsing a simple query language consiting of QueryNodes, subclassed as
QueryOperators, QueryCommands and QueryTokens. QueryToken identifies a Token by name. QueryCommand represents predefined
filters. QueryOperator defines the syntactic relationship.
QueryNode examples:
"A" -> QueryToken that identifies the Token named A
class -> QueryCommand that filters all Nodes that are classes
. -> QueryOperator that concatenates filters
QueryExamples:
"A".class -> All Tokens named A that are classes
method.(private|protected) -> All methods that are private or protected
"A".member -> All members of A
"A":field.!const -> All fields of A that are not const (':' can be used instead of '.member')
QueryTree checks for correct operator precedence and validity of the query.
All QueryCommands can be found in data/query/QueryCommand.cpp
All QueryOperators can be found in data/query/QueryOperator.cpp
The parsed QueryTree is then passed to the class GraphFilterConductor, which is capable of applying the query on a
Graph. Each part of the query gets assigned a GraphFilter that filters the input Graph in order of node precedence. The
class SubGraph is used as intermediate container, only holding bare pointers to Nodes and Edges. The output Graph holds
all Nodes that match the query.
MessageActivateTokens is used to show all of the results in the CodeView. The GraphView currently only shows the first
Node of the results.
bug id = #6
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
#include "data/graph/FilterableGraph.h"
|
||||
|
||||
#include "data/graph/Edge.h"
|
||||
#include "data/graph/Node.h"
|
||||
|
||||
FilterableGraph::FilterableGraph()
|
||||
{
|
||||
}
|
||||
|
||||
FilterableGraph::~FilterableGraph()
|
||||
{
|
||||
}
|
||||
|
||||
void FilterableGraph::print(std::ostream& ostream) const
|
||||
{
|
||||
ostream << "Graph:\n";
|
||||
ostream << "nodes (" << getNodeCount() << ")\n";
|
||||
forEachNode(
|
||||
[&ostream](Node* n)
|
||||
{
|
||||
ostream << *n << '\n';
|
||||
}
|
||||
);
|
||||
|
||||
ostream << "edges (" << getEdgeCount() << ")\n";
|
||||
forEachEdge(
|
||||
[&ostream](Edge* e)
|
||||
{
|
||||
ostream << *e << '\n';
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef FILTERABLE_GRAPH_H
|
||||
#define FILTERABLE_GRAPH_H
|
||||
|
||||
#include <functional>
|
||||
#include <ostream>
|
||||
|
||||
class Edge;
|
||||
class Node;
|
||||
class Token;
|
||||
|
||||
class FilterableGraph
|
||||
{
|
||||
public:
|
||||
FilterableGraph();
|
||||
virtual ~FilterableGraph();
|
||||
|
||||
virtual void copy(const FilterableGraph* other) = 0;
|
||||
virtual void clear() = 0;
|
||||
|
||||
virtual void add(const FilterableGraph* other) = 0;
|
||||
|
||||
virtual void forEachNode(std::function<void(Node*)> func) const = 0;
|
||||
virtual void forEachEdge(std::function<void(Edge*)> func) const = 0;
|
||||
virtual void forEachToken(std::function<void(Token*)> func) const = 0;
|
||||
|
||||
virtual void addNode(Node* node) = 0;
|
||||
virtual void addEdge(Edge* edge) = 0;
|
||||
|
||||
virtual size_t getNodeCount() const = 0;
|
||||
virtual size_t getEdgeCount() const = 0;
|
||||
|
||||
void print(std::ostream& ostream) const;
|
||||
};
|
||||
|
||||
#endif // FILTERABLE_GRAPH_H
|
||||
@@ -14,6 +14,79 @@ Graph::~Graph()
|
||||
m_nodes.clear();
|
||||
}
|
||||
|
||||
void Graph::copy(const FilterableGraph* other)
|
||||
{
|
||||
clear();
|
||||
add(other);
|
||||
}
|
||||
|
||||
void Graph::clear()
|
||||
{
|
||||
m_edges.clear();
|
||||
m_nodes.clear();
|
||||
}
|
||||
|
||||
void Graph::add(const FilterableGraph* other)
|
||||
{
|
||||
other->forEachNode(std::bind(&Graph::addNode, this, std::placeholders::_1));
|
||||
other->forEachEdge(std::bind(&Graph::addEdge, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void Graph::forEachNode(std::function<void(Node*)> func) const
|
||||
{
|
||||
for (const std::pair<Id, std::shared_ptr<Node>>& node : m_nodes)
|
||||
{
|
||||
func(node.second.get());
|
||||
}
|
||||
}
|
||||
|
||||
void Graph::forEachEdge(std::function<void(Edge*)> func) const
|
||||
{
|
||||
for (const std::pair<Id, std::shared_ptr<Edge>>& edge : m_edges)
|
||||
{
|
||||
func(edge.second.get());
|
||||
}
|
||||
}
|
||||
|
||||
void Graph::forEachToken(std::function<void(Token*)> func) const
|
||||
{
|
||||
forEachNode(func);
|
||||
forEachEdge(func);
|
||||
}
|
||||
|
||||
void Graph::addNode(Node* node)
|
||||
{
|
||||
addNodeAsPlainCopy(node);
|
||||
}
|
||||
|
||||
void Graph::addEdge(Edge* edge)
|
||||
{
|
||||
if (getNodeById(edge->getFrom()->getId()) && getNodeById(edge->getTo()->getId()))
|
||||
{
|
||||
addEdgeAsPlainCopy(edge);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Graph::getNodeCount() const
|
||||
{
|
||||
return m_nodes.size();
|
||||
}
|
||||
|
||||
size_t Graph::getEdgeCount() const
|
||||
{
|
||||
return m_edges.size();
|
||||
}
|
||||
|
||||
const std::map<Id, std::shared_ptr<Node>>& Graph::getNodes() const
|
||||
{
|
||||
return m_nodes;
|
||||
}
|
||||
|
||||
const std::map<Id, std::shared_ptr<Edge>>& Graph::getEdges() const
|
||||
{
|
||||
return m_edges;
|
||||
}
|
||||
|
||||
Node* Graph::getNode(const std::string& fullName) const
|
||||
{
|
||||
std::deque<std::string> names = utility::split<std::deque<std::string>>(fullName, DELIMITER);
|
||||
@@ -256,44 +329,6 @@ Token* Graph::findToken(std::function<bool(Token*)> func) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Graph::forEachNode(std::function<void(Node*)> func) const
|
||||
{
|
||||
for (const std::pair<Id, std::shared_ptr<Node>>& node : m_nodes)
|
||||
{
|
||||
func(node.second.get());
|
||||
}
|
||||
}
|
||||
|
||||
void Graph::forEachEdge(std::function<void(Edge*)> func) const
|
||||
{
|
||||
for (const std::pair<Id, std::shared_ptr<Edge>>& edge : m_edges)
|
||||
{
|
||||
func(edge.second.get());
|
||||
}
|
||||
}
|
||||
|
||||
void Graph::forEachToken(std::function<void(Token*)> func) const
|
||||
{
|
||||
forEachNode(func);
|
||||
forEachEdge(func);
|
||||
}
|
||||
|
||||
void Graph::clear()
|
||||
{
|
||||
m_edges.clear();
|
||||
m_nodes.clear();
|
||||
}
|
||||
|
||||
const std::map<Id, std::shared_ptr<Node> >& Graph::getNodes() const
|
||||
{
|
||||
return m_nodes;
|
||||
}
|
||||
|
||||
const std::map<Id, std::shared_ptr<Edge> >& Graph::getEdges() const
|
||||
{
|
||||
return m_edges;
|
||||
}
|
||||
|
||||
Node* Graph::addNodeAsPlainCopy(Node* node)
|
||||
{
|
||||
Node* n = getNodeById(node->getId());
|
||||
@@ -410,22 +445,6 @@ void Graph::removeEdgeInternal(Edge* edge)
|
||||
|
||||
std::ostream& operator<<(std::ostream& ostream, const Graph& graph)
|
||||
{
|
||||
ostream << "Graph:\n";
|
||||
ostream << "nodes (" << graph.getNodes().size() << ")\n";
|
||||
graph.forEachNode(
|
||||
[&ostream](Node* n)
|
||||
{
|
||||
ostream << *n << '\n';
|
||||
}
|
||||
);
|
||||
|
||||
ostream << "edges (" << graph.getEdges().size() << ")\n";
|
||||
graph.forEachEdge(
|
||||
[&ostream](Edge* e)
|
||||
{
|
||||
ostream << *e << '\n';
|
||||
}
|
||||
);
|
||||
|
||||
graph.print(ostream);
|
||||
return ostream;
|
||||
}
|
||||
|
||||
+21
-13
@@ -3,18 +3,38 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <deque>
|
||||
|
||||
#include "data/graph/Edge.h"
|
||||
#include "data/graph/FilterableGraph.h"
|
||||
#include "data/graph/Node.h"
|
||||
|
||||
class Graph
|
||||
: public FilterableGraph
|
||||
{
|
||||
public:
|
||||
Graph();
|
||||
virtual ~Graph();
|
||||
|
||||
// FilterableGraph implementation
|
||||
virtual void copy(const FilterableGraph* other);
|
||||
virtual void clear();
|
||||
|
||||
virtual void add(const FilterableGraph* other);
|
||||
|
||||
virtual void forEachNode(std::function<void(Node*)> func) const;
|
||||
virtual void forEachEdge(std::function<void(Edge*)> func) const;
|
||||
virtual void forEachToken(std::function<void(Token*)> func) const;
|
||||
|
||||
virtual void addNode(Node* node);
|
||||
virtual void addEdge(Edge* edge);
|
||||
|
||||
virtual size_t getNodeCount() const;
|
||||
virtual size_t getEdgeCount() const;
|
||||
|
||||
const std::map<Id, std::shared_ptr<Node>>& getNodes() const;
|
||||
const std::map<Id, std::shared_ptr<Edge>>& getEdges() const;
|
||||
|
||||
Node* getNode(const std::string& fullName) const;
|
||||
Edge* getEdge(Edge::EdgeType type, Node* from, Node* to) const;
|
||||
|
||||
@@ -39,19 +59,9 @@ public:
|
||||
Edge* findEdge(std::function<bool(Edge*)> func) const;
|
||||
Token* findToken(std::function<bool(Token*)> func) const;
|
||||
|
||||
void forEachNode(std::function<void(Node*)> func) const;
|
||||
void forEachEdge(std::function<void(Edge*)> func) const;
|
||||
void forEachToken(std::function<void(Token*)> func) const;
|
||||
|
||||
Node* addNodeAsPlainCopy(Node* node);
|
||||
Edge* addEdgeAsPlainCopy(Edge* edge);
|
||||
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
const std::map<Id, std::shared_ptr<Node>>& getNodes() const;
|
||||
const std::map<Id, std::shared_ptr<Edge>>& getEdges() const;
|
||||
|
||||
private:
|
||||
static const std::string DELIMITER;
|
||||
|
||||
@@ -65,8 +75,6 @@ private:
|
||||
|
||||
std::map<Id, std::shared_ptr<Node>> m_nodes;
|
||||
std::map<Id, std::shared_ptr<Edge>> m_edges;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& ostream, const Graph& graph);
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& ostream, const Graph& graph);
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
#include "data/graph/SubGraph.h"
|
||||
|
||||
#include "data/graph/Edge.h"
|
||||
#include "data/graph/Node.h"
|
||||
|
||||
SubGraph::SubGraph()
|
||||
{
|
||||
}
|
||||
|
||||
SubGraph::~SubGraph()
|
||||
{
|
||||
}
|
||||
|
||||
void SubGraph::copy(const FilterableGraph* other)
|
||||
{
|
||||
clear();
|
||||
add(other);
|
||||
}
|
||||
|
||||
void SubGraph::clear()
|
||||
{
|
||||
m_edges.clear();
|
||||
m_nodes.clear();
|
||||
}
|
||||
|
||||
void SubGraph::add(const FilterableGraph* other)
|
||||
{
|
||||
other->forEachNode(std::bind(&SubGraph::addNode, this, std::placeholders::_1));
|
||||
other->forEachEdge(std::bind(&SubGraph::addEdge, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void SubGraph::forEachNode(std::function<void(Node*)> func) const
|
||||
{
|
||||
for (const std::pair<Id, Node*>& node : m_nodes)
|
||||
{
|
||||
func(node.second);
|
||||
}
|
||||
}
|
||||
|
||||
void SubGraph::forEachEdge(std::function<void(Edge*)> func) const
|
||||
{
|
||||
for (const std::pair<Id, Edge*>& edge : m_edges)
|
||||
{
|
||||
func(edge.second);
|
||||
}
|
||||
}
|
||||
|
||||
void SubGraph::forEachToken(std::function<void(Token*)> func) const
|
||||
{
|
||||
forEachNode(func);
|
||||
forEachEdge(func);
|
||||
}
|
||||
|
||||
void SubGraph::addNode(Node* node)
|
||||
{
|
||||
m_nodes.emplace(node->getId(), node);
|
||||
}
|
||||
|
||||
void SubGraph::addEdge(Edge* edge)
|
||||
{
|
||||
m_edges.emplace(edge->getId(), edge);
|
||||
}
|
||||
|
||||
size_t SubGraph::getNodeCount() const
|
||||
{
|
||||
return m_nodes.size();
|
||||
}
|
||||
|
||||
size_t SubGraph::getEdgeCount() const
|
||||
{
|
||||
return m_edges.size();
|
||||
}
|
||||
|
||||
std::vector<Id> SubGraph::getTokenIds() const
|
||||
{
|
||||
std::vector<Id> ids;
|
||||
for (const std::pair<Id, Node*>& node : m_nodes)
|
||||
{
|
||||
ids.push_back(node.first);
|
||||
}
|
||||
|
||||
for (const std::pair<Id, Edge*>& edge : m_edges)
|
||||
{
|
||||
ids.push_back(edge.first);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
void SubGraph::subtract(const SubGraph& other)
|
||||
{
|
||||
for (const std::pair<Id, Node*>& node : other.m_nodes)
|
||||
{
|
||||
m_nodes.erase(node.first);
|
||||
}
|
||||
|
||||
for (const std::pair<Id, Edge*>& edge : other.m_edges)
|
||||
{
|
||||
m_edges.erase(edge.first);
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& ostream, const SubGraph& graph)
|
||||
{
|
||||
graph.print(ostream);
|
||||
return ostream;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef SUB_GRAPH_H
|
||||
#define SUB_GRAPH_H
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "data/graph/FilterableGraph.h"
|
||||
#include "utility/types.h"
|
||||
|
||||
class Edge;
|
||||
class Node;
|
||||
class Token;
|
||||
|
||||
class SubGraph
|
||||
: public FilterableGraph
|
||||
{
|
||||
public:
|
||||
SubGraph();
|
||||
virtual ~SubGraph();
|
||||
|
||||
// FilterableGraph implementation
|
||||
virtual void copy(const FilterableGraph* other);
|
||||
virtual void clear();
|
||||
|
||||
virtual void add(const FilterableGraph* other);
|
||||
|
||||
virtual void forEachNode(std::function<void(Node*)> func) const;
|
||||
virtual void forEachEdge(std::function<void(Edge*)> func) const;
|
||||
virtual void forEachToken(std::function<void(Token*)> func) const;
|
||||
|
||||
virtual void addNode(Node* node);
|
||||
virtual void addEdge(Edge* edge);
|
||||
|
||||
virtual size_t getNodeCount() const;
|
||||
virtual size_t getEdgeCount() const;
|
||||
|
||||
std::vector<Id> getTokenIds() const;
|
||||
|
||||
void subtract(const SubGraph& other);
|
||||
|
||||
private:
|
||||
std::map<Id, Node*> m_nodes;
|
||||
std::map<Id, Edge*> m_edges;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& ostream, const SubGraph& graph);
|
||||
|
||||
#endif // SUB_GRAPH_H
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "data/graph/filter/GraphFilter.h"
|
||||
|
||||
#include "data/graph/Edge.h"
|
||||
#include "data/graph/FilterableGraph.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
GraphFilter::GraphFilter()
|
||||
: m_outGraph(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
GraphFilter::~GraphFilter()
|
||||
{
|
||||
}
|
||||
|
||||
void GraphFilter::apply(const FilterableGraph* in, FilterableGraph* out)
|
||||
{
|
||||
if (!in || !out)
|
||||
{
|
||||
LOG_ERROR("GraphFilter not called with correct pointers.");
|
||||
return;
|
||||
}
|
||||
else if (in == out)
|
||||
{
|
||||
LOG_ERROR("In and out graphs are the same.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_outGraph = out;
|
||||
|
||||
in->forEachNode(
|
||||
[this](Node* node)
|
||||
{
|
||||
visitNode(node);
|
||||
}
|
||||
);
|
||||
|
||||
// in->forEachEdge(
|
||||
// [this](Edge* edge)
|
||||
// {
|
||||
// visitEdge(edge);
|
||||
// }
|
||||
// );
|
||||
|
||||
m_outGraph = nullptr;
|
||||
}
|
||||
|
||||
void GraphFilter::visitNode(Node* node)
|
||||
{
|
||||
}
|
||||
|
||||
// void GraphFilter::visitEdge(Edge* edge)
|
||||
// {
|
||||
// }
|
||||
|
||||
void GraphFilter::addNode(Node* node)
|
||||
{
|
||||
m_outGraph->addNode(node);
|
||||
}
|
||||
|
||||
void GraphFilter::addEdge(Edge* edge)
|
||||
{
|
||||
m_outGraph->addNode(edge->getFrom());
|
||||
m_outGraph->addNode(edge->getTo());
|
||||
m_outGraph->addEdge(edge);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef GRAPH_FILTER_H
|
||||
#define GRAPH_FILTER_H
|
||||
|
||||
class Edge;
|
||||
class FilterableGraph;
|
||||
class Node;
|
||||
|
||||
class GraphFilter
|
||||
{
|
||||
public:
|
||||
GraphFilter();
|
||||
virtual ~GraphFilter();
|
||||
|
||||
void apply(const FilterableGraph* in, FilterableGraph* out);
|
||||
|
||||
protected:
|
||||
virtual void visitNode(Node* node);
|
||||
// virtual void visitEdge(Edge* edge);
|
||||
|
||||
void addNode(Node* node);
|
||||
void addEdge(Edge* edge);
|
||||
|
||||
private:
|
||||
FilterableGraph* m_outGraph;
|
||||
};
|
||||
|
||||
#endif // GRAPH_FILTER_H
|
||||
@@ -0,0 +1,178 @@
|
||||
#include "data/graph/filter/GraphFilterConductor.h"
|
||||
|
||||
#include "data/graph/filter/GraphFilter.h"
|
||||
#include "data/graph/filter/GraphFilterImplementations.h"
|
||||
#include "data/graph/SubGraph.h"
|
||||
#include "data/query/QueryCommand.h"
|
||||
#include "data/query/QueryNode.h"
|
||||
#include "data/query/QueryOperator.h"
|
||||
#include "data/query/QueryToken.h"
|
||||
#include "data/query/QueryTree.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
GraphFilterConductor::GraphFilterConductor()
|
||||
{
|
||||
}
|
||||
|
||||
GraphFilterConductor::~GraphFilterConductor()
|
||||
{
|
||||
}
|
||||
|
||||
void GraphFilterConductor::filter(const QueryTree* tree, const FilterableGraph* in, FilterableGraph* out) const
|
||||
{
|
||||
if (tree->isValid())
|
||||
{
|
||||
filterRecursively(tree->getRoot().get(), in, out);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphFilterConductor::filterRecursively(const QueryNode* node, const FilterableGraph* in, FilterableGraph* out) const
|
||||
{
|
||||
if (node->isOperator())
|
||||
{
|
||||
filterOperatorNode(dynamic_cast<const QueryOperator*>(node), in, out);
|
||||
}
|
||||
else if (node->isCommand())
|
||||
{
|
||||
filterCommandNode(dynamic_cast<const QueryCommand*>(node), in, out);
|
||||
}
|
||||
else if (node->isToken())
|
||||
{
|
||||
filterTokenNode(dynamic_cast<const QueryToken*>(node), in, out);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphFilterConductor::filterOperatorNode(const QueryOperator* node, const FilterableGraph* in, FilterableGraph* out) const
|
||||
{
|
||||
switch (node->getType())
|
||||
{
|
||||
case QueryOperator::OPERATOR_NOT:
|
||||
{
|
||||
SubGraph sub, sub2;
|
||||
filterRecursively(node->getRight().get(), in, &sub);
|
||||
|
||||
sub2.copy(in);
|
||||
sub2.subtract(sub);
|
||||
out->add(&sub2);
|
||||
}
|
||||
break;
|
||||
|
||||
case QueryOperator::OPERATOR_SUB:
|
||||
case QueryOperator::OPERATOR_AND:
|
||||
{
|
||||
SubGraph sub;
|
||||
filterRecursively(node->getLeft().get(), in, &sub);
|
||||
filterRecursively(node->getRight().get(), &sub, out);
|
||||
}
|
||||
break;
|
||||
|
||||
case QueryOperator::OPERATOR_HAS:
|
||||
{
|
||||
SubGraph sub, sub2;
|
||||
filterRecursively(node->getLeft().get(), in, &sub);
|
||||
GraphFilterCommandMember().apply(&sub, &sub2);
|
||||
filterRecursively(node->getRight().get(), &sub2, out);
|
||||
}
|
||||
break;
|
||||
|
||||
case QueryOperator::OPERATOR_OR:
|
||||
filterRecursively(node->getLeft().get(), in, out);
|
||||
filterRecursively(node->getRight().get(), in, out);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphFilterConductor::filterCommandNode(const QueryCommand* node, const FilterableGraph* in, FilterableGraph* out) const
|
||||
{
|
||||
switch (node->getType())
|
||||
{
|
||||
case QueryCommand::COMMAND_MEMBER:
|
||||
GraphFilterCommandMember().apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_PARENT:
|
||||
GraphFilterCommandParent().apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_FUNCTION:
|
||||
GraphFilterCommandNodeType(Node::NODE_FUNCTION).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_GLOBAL_VARIABLE:
|
||||
GraphFilterCommandNodeType(Node::NODE_GLOBAL_VARIABLE).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_CLASS:
|
||||
GraphFilterCommandNodeType(Node::NODE_CLASS).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_METHOD:
|
||||
GraphFilterCommandNodeType(Node::NODE_METHOD).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_FIELD:
|
||||
GraphFilterCommandNodeType(Node::NODE_FIELD).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_NAMESPACE:
|
||||
GraphFilterCommandNodeType(Node::NODE_NAMESPACE).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_STRUCT:
|
||||
GraphFilterCommandNodeType(Node::NODE_STRUCT).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_ENUM:
|
||||
GraphFilterCommandNodeType(Node::NODE_ENUM).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_TYPEDEF:
|
||||
GraphFilterCommandNodeType(Node::NODE_TYPEDEF).apply(in, out);
|
||||
break;
|
||||
|
||||
case QueryCommand::COMMAND_CONST:
|
||||
GraphFilterCommandConst().apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_STATIC:
|
||||
GraphFilterCommandStatic().apply(in, out);
|
||||
break;
|
||||
|
||||
case QueryCommand::COMMAND_VIRTUAL:
|
||||
GraphFilterCommandAbstractionType(TokenComponentAbstraction::ABSTRACTION_VIRTUAL).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_PURE_VIRTUAL:
|
||||
GraphFilterCommandAbstractionType(TokenComponentAbstraction::ABSTRACTION_PURE_VIRTUAL).apply(in, out);
|
||||
break;
|
||||
|
||||
case QueryCommand::COMMAND_PUBLIC:
|
||||
GraphFilterCommandAccessType(TokenComponentAccess::ACCESS_PUBLIC).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_PROTECTED:
|
||||
GraphFilterCommandAccessType(TokenComponentAccess::ACCESS_PROTECTED).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_PRIVATE:
|
||||
GraphFilterCommandAccessType(TokenComponentAccess::ACCESS_PRIVATE).apply(in, out);
|
||||
break;
|
||||
|
||||
case QueryCommand::COMMAND_CALLER:
|
||||
GraphFilterCommandCall(true).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_CALLEE:
|
||||
GraphFilterCommandCall(false).apply(in, out);
|
||||
break;
|
||||
|
||||
case QueryCommand::COMMAND_USAGE:
|
||||
GraphFilterCommandUsage().apply(in, out);
|
||||
break;
|
||||
|
||||
case QueryCommand::COMMAND_SUPER_CLASS:
|
||||
GraphFilterCommandInheritance(true).apply(in, out);
|
||||
break;
|
||||
case QueryCommand::COMMAND_SUB_CLASS:
|
||||
GraphFilterCommandInheritance(false).apply(in, out);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERROR_STREAM(<< "QueryCommand not supported: " << node->getType());
|
||||
GraphFilter().apply(in, out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphFilterConductor::filterTokenNode(const QueryToken* node, const FilterableGraph* in, FilterableGraph* out) const
|
||||
{
|
||||
GraphFilterToken(node->getName()).apply(in, out);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef GRAPH_FILTER_CONDUCTOR_H
|
||||
#define GRAPH_FILTER_CONDUCTOR_H
|
||||
|
||||
class FilterableGraph;
|
||||
class QueryCommand;
|
||||
class QueryNode;
|
||||
class QueryOperator;
|
||||
class QueryToken;
|
||||
class QueryTree;
|
||||
|
||||
class GraphFilterConductor
|
||||
{
|
||||
public:
|
||||
GraphFilterConductor();
|
||||
~GraphFilterConductor();
|
||||
|
||||
void filter(const QueryTree* tree, const FilterableGraph* in, FilterableGraph* out) const;
|
||||
|
||||
private:
|
||||
void filterRecursively(const QueryNode* node, const FilterableGraph* in, FilterableGraph* out) const;
|
||||
void filterOperatorNode(const QueryOperator* node, const FilterableGraph* in, FilterableGraph* out) const;
|
||||
void filterCommandNode(const QueryCommand* node, const FilterableGraph* in, FilterableGraph* out) const;
|
||||
void filterTokenNode(const QueryToken* node, const FilterableGraph* in, FilterableGraph* out) const;
|
||||
};
|
||||
|
||||
#endif // GRAPH_FILTER_CONDUCTOR_H
|
||||
@@ -0,0 +1,280 @@
|
||||
#ifndef GRAPH_FILTER_IMPLEMENTATIONS_H
|
||||
#define GRAPH_FILTER_IMPLEMENTATIONS_H
|
||||
|
||||
#include "data/graph/Edge.h"
|
||||
#include "data/graph/filter/GraphFilter.h"
|
||||
#include "data/graph/Node.h"
|
||||
#include "data/graph/token_component/TokenComponentAbstraction.h"
|
||||
#include "data/graph/token_component/TokenComponentAccess.h"
|
||||
#include "data/graph/token_component/TokenComponentConst.h"
|
||||
#include "data/graph/token_component/TokenComponentDataType.h"
|
||||
#include "data/graph/token_component/TokenComponentStatic.h"
|
||||
|
||||
/*
|
||||
* empty GraphFilterImplementation for copy-pasting
|
||||
*
|
||||
|
||||
class GraphFilter: public GraphFilter
|
||||
{
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
class GraphFilterCommandMember
|
||||
: public GraphFilter
|
||||
{
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
node->forEachChildNode(
|
||||
[this](Node* n)
|
||||
{
|
||||
addNode(n);
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
class GraphFilterCommandParent
|
||||
: public GraphFilter
|
||||
{
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
Node* parent = node->getParentNode();
|
||||
if (parent)
|
||||
{
|
||||
addNode(parent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class GraphFilterCommandNodeType
|
||||
: public GraphFilter
|
||||
{
|
||||
public:
|
||||
GraphFilterCommandNodeType(Node::NodeType type)
|
||||
: m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
if (node->getType() == m_type)
|
||||
{
|
||||
addNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const Node::NodeType m_type;
|
||||
};
|
||||
|
||||
class GraphFilterCommandConst
|
||||
: public GraphFilter
|
||||
{
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
if (node->getType() == Node::NODE_METHOD && node->getComponent<TokenComponentConst>())
|
||||
{
|
||||
addNode(node);
|
||||
}
|
||||
|
||||
Edge* edge = node->findEdgeOfType(Edge::EDGE_TYPE_OF);
|
||||
if (!edge)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TokenComponentDataType* type = edge->getComponent<TokenComponentDataType>();
|
||||
if (type && type->isConstQualified())
|
||||
{
|
||||
addNode(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class GraphFilterCommandStatic
|
||||
: public GraphFilter
|
||||
{
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
if (node->getComponent<TokenComponentStatic>())
|
||||
{
|
||||
addNode(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class GraphFilterCommandAccessType
|
||||
: public GraphFilter
|
||||
{
|
||||
public:
|
||||
GraphFilterCommandAccessType(TokenComponentAccess::AccessType type)
|
||||
: m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
Edge* edge = node->getMemberEdge();
|
||||
if (!edge)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TokenComponentAccess* access = edge->getComponent<TokenComponentAccess>();
|
||||
if (access && access->getAccess() == m_type)
|
||||
{
|
||||
addNode(edge->getTo());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const TokenComponentAccess::AccessType m_type;
|
||||
};
|
||||
|
||||
class GraphFilterCommandAbstractionType
|
||||
: public GraphFilter
|
||||
{
|
||||
public:
|
||||
GraphFilterCommandAbstractionType(TokenComponentAbstraction::AbstractionType type)
|
||||
: m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
TokenComponentAbstraction* abstraction = node->getComponent<TokenComponentAbstraction>();
|
||||
if (abstraction && abstraction->getAbstraction() == m_type)
|
||||
{
|
||||
addNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const TokenComponentAbstraction::AbstractionType m_type;
|
||||
};
|
||||
|
||||
class GraphFilterCommandCall
|
||||
: public GraphFilter
|
||||
{
|
||||
public:
|
||||
GraphFilterCommandCall(bool callers)
|
||||
: m_callers(callers)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
node->forEachEdgeOfType(Edge::EDGE_CALL,
|
||||
[this, node](Edge* edge)
|
||||
{
|
||||
Node* from = edge->getFrom();
|
||||
Node* to = edge->getTo();
|
||||
|
||||
if (m_callers && node == to)
|
||||
{
|
||||
addNode(from);
|
||||
}
|
||||
else if (!m_callers && node == from)
|
||||
{
|
||||
addNode(to);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
const bool m_callers;
|
||||
};
|
||||
|
||||
class GraphFilterCommandUsage
|
||||
: public GraphFilter
|
||||
{
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
Edge::EdgeTypeMask mask;
|
||||
mask = Edge::EDGE_TYPE_OF | Edge::EDGE_RETURN_TYPE_OF | Edge::EDGE_PARAMETER_TYPE_OF;
|
||||
mask = Edge::EDGE_TYPE_USAGE | Edge::EDGE_USAGE | Edge::EDGE_TYPEDEF_OF | mask;
|
||||
|
||||
node->forEachEdge(
|
||||
[this, node, mask](Edge* edge)
|
||||
{
|
||||
if (node == edge->getTo() && edge->isType(mask))
|
||||
{
|
||||
addNode(edge->getFrom());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
class GraphFilterCommandInheritance
|
||||
: public GraphFilter
|
||||
{
|
||||
public:
|
||||
GraphFilterCommandInheritance(bool super)
|
||||
: m_super(super)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
node->forEachEdgeOfType(Edge::EDGE_INHERITANCE,
|
||||
[this, node](Edge* edge)
|
||||
{
|
||||
Node* from = edge->getFrom();
|
||||
Node* to = edge->getTo();
|
||||
|
||||
if (m_super && node == from)
|
||||
{
|
||||
addNode(to);
|
||||
}
|
||||
else if (!m_super && node == to)
|
||||
{
|
||||
addNode(from);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
const bool m_super;
|
||||
};
|
||||
|
||||
|
||||
class GraphFilterToken
|
||||
: public GraphFilter
|
||||
{
|
||||
public:
|
||||
GraphFilterToken(const std::string& name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void visitNode(Node* node)
|
||||
{
|
||||
if (node->getName() == m_name)
|
||||
{
|
||||
addNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string& m_name;
|
||||
};
|
||||
|
||||
#endif // GRAPH_FILTER_IMPLEMENTATIONS_H
|
||||
@@ -28,3 +28,8 @@ std::string TokenComponentDataType::getQualifiedTypeName(const std::string& type
|
||||
{
|
||||
return m_modifierStack.applyTo(m_qualifierList.applyTo(typeName));
|
||||
}
|
||||
|
||||
bool TokenComponentDataType::isConstQualified() const
|
||||
{
|
||||
return m_qualifierList.hasQualifier(DataTypeQualifierList::QUALIFIER_CONST);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ public:
|
||||
DataType getDataType(const std::string& typeName) const;
|
||||
std::string getQualifiedTypeName(const std::string& typeName) const;
|
||||
|
||||
bool isConstQualified() const;
|
||||
|
||||
private:
|
||||
const DataTypeQualifierList m_qualifierList;
|
||||
const DataTypeModifierStack m_modifierStack;
|
||||
|
||||
Reference in New Issue
Block a user