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:
@@ -40,7 +40,7 @@ public:
|
||||
private:
|
||||
int m_importantValue;
|
||||
char m_importanterValue;
|
||||
float m_importantestValue;
|
||||
const float m_importantestValue;
|
||||
};
|
||||
|
||||
A globalA(' ');
|
||||
@@ -52,6 +52,13 @@ public:
|
||||
: A('b')
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~B()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual float getNumber() = 0;
|
||||
};
|
||||
|
||||
class C
|
||||
@@ -61,13 +68,20 @@ public:
|
||||
: m_valuable(0)
|
||||
{
|
||||
globalA.doImportantStuff();
|
||||
s_count++;
|
||||
}
|
||||
|
||||
~C()
|
||||
{
|
||||
s_count--;
|
||||
}
|
||||
|
||||
void solveAllProblems()
|
||||
static int getCount()
|
||||
{
|
||||
return s_count;
|
||||
}
|
||||
|
||||
void solveAllProblems() const
|
||||
{
|
||||
A aInstance('a');
|
||||
aInstance.doImportantStuff();
|
||||
@@ -75,6 +89,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
static int s_count;
|
||||
int m_valuable;
|
||||
};
|
||||
|
||||
|
||||
@@ -71,6 +71,12 @@ add_files(
|
||||
data/access/GraphAccessProxy.cpp
|
||||
data/access/GraphAccessProxy.h
|
||||
|
||||
data/graph/filter/GraphFilter.cpp
|
||||
data/graph/filter/GraphFilter.h
|
||||
data/graph/filter/GraphFilterConductor.cpp
|
||||
data/graph/filter/GraphFilterConductor.h
|
||||
data/graph/filter/GraphFilterImplementations.h
|
||||
|
||||
data/graph/token_component/TokenComponent.cpp
|
||||
data/graph/token_component/TokenComponent.h
|
||||
data/graph/token_component/TokenComponentAbstraction.cpp
|
||||
@@ -88,10 +94,14 @@ add_files(
|
||||
|
||||
data/graph/Edge.cpp
|
||||
data/graph/Edge.h
|
||||
data/graph/FilterableGraph.cpp
|
||||
data/graph/FilterableGraph.h
|
||||
data/graph/Graph.cpp
|
||||
data/graph/Graph.h
|
||||
data/graph/Node.cpp
|
||||
data/graph/Node.h
|
||||
data/graph/SubGraph.cpp
|
||||
data/graph/SubGraph.h
|
||||
data/graph/Token.cpp
|
||||
data/graph/Token.h
|
||||
|
||||
@@ -117,6 +127,17 @@ add_files(
|
||||
data/parser/ParseVariable.cpp
|
||||
data/parser/ParseVariable.h
|
||||
|
||||
data/query/QueryCommand.cpp
|
||||
data/query/QueryCommand.h
|
||||
data/query/QueryNode.cpp
|
||||
data/query/QueryNode.h
|
||||
data/query/QueryOperator.cpp
|
||||
data/query/QueryOperator.h
|
||||
data/query/QueryToken.cpp
|
||||
data/query/QueryToken.h
|
||||
data/query/QueryTree.cpp
|
||||
data/query/QueryTree.h
|
||||
|
||||
data/type/modifier/DataTypeModifier.cpp
|
||||
data/type/modifier/DataTypeModifier.h
|
||||
data/type/modifier/DataTypeModifierArray.cpp
|
||||
|
||||
@@ -18,14 +18,13 @@ CodeController::~CodeController()
|
||||
{
|
||||
}
|
||||
|
||||
void CodeController::setActiveTokenId(Id id)
|
||||
void CodeController::setActiveTokenIds(const std::vector<Id>& ids)
|
||||
{
|
||||
const uint lineRadius = 2;
|
||||
|
||||
getView()->clearCodeSnippets();
|
||||
|
||||
std::vector<Id> activeTokenIds = m_graphAccess->getActiveTokenIdsForId(id);
|
||||
std::vector<Id> locationIds = m_graphAccess->getLocationIdsForTokenIds(activeTokenIds);
|
||||
std::vector<Id> locationIds = m_graphAccess->getLocationIdsForTokenIds(ids);
|
||||
|
||||
TokenLocationCollection collection = m_locationAccess->getTokenLocationsForLocationIds(locationIds);
|
||||
collection.forEachTokenLocationFile(
|
||||
@@ -49,7 +48,7 @@ void CodeController::setActiveTokenId(Id id)
|
||||
params.startLineNumber = firstLineNumber;
|
||||
params.locationFile =
|
||||
m_locationAccess->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber);
|
||||
params.activeTokenIds = activeTokenIds;
|
||||
params.activeTokenIds = ids;
|
||||
|
||||
getView()->addCodeSnippet(params);
|
||||
}
|
||||
@@ -59,7 +58,21 @@ void CodeController::setActiveTokenId(Id id)
|
||||
|
||||
void CodeController::handleMessage(MessageActivateToken* message)
|
||||
{
|
||||
setActiveTokenId(message->tokenId);
|
||||
std::vector<Id> activeTokenIds = m_graphAccess->getActiveTokenIdsForId(message->tokenId);
|
||||
setActiveTokenIds(activeTokenIds);
|
||||
}
|
||||
|
||||
void CodeController::handleMessage(MessageActivateTokens* message)
|
||||
{
|
||||
if (message->tokenIds.size() == 1)
|
||||
{
|
||||
std::vector<Id> activeTokenIds = m_graphAccess->getActiveTokenIdsForId(message->tokenIds[0]);
|
||||
setActiveTokenIds(activeTokenIds);
|
||||
}
|
||||
else
|
||||
{
|
||||
setActiveTokenIds(message->tokenIds);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeController::handleMessage(MessageRefresh* message)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "component/controller/Controller.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateToken.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
#include "utility/messaging/type/MessageRefresh.h"
|
||||
#include "utility/messaging/type/MessageShowFile.h"
|
||||
#include "utility/types.h"
|
||||
@@ -24,6 +25,7 @@ struct AnnotatedText
|
||||
class CodeController
|
||||
: public Controller
|
||||
, public MessageListener<MessageActivateToken>
|
||||
, public MessageListener<MessageActivateTokens>
|
||||
, public MessageListener<MessageRefresh>
|
||||
, public MessageListener<MessageShowFile>
|
||||
{
|
||||
@@ -31,10 +33,11 @@ public:
|
||||
CodeController(GraphAccess* graphAccess, LocationAccess* locationAccess);
|
||||
~CodeController();
|
||||
|
||||
void setActiveTokenId(Id id);
|
||||
void setActiveTokenIds(const std::vector<Id>& ids);
|
||||
|
||||
private:
|
||||
virtual void handleMessage(MessageActivateToken* message);
|
||||
virtual void handleMessage(MessageActivateTokens* message);
|
||||
virtual void handleMessage(MessageRefresh* message);
|
||||
virtual void handleMessage(MessageShowFile* message);
|
||||
|
||||
|
||||
@@ -22,6 +22,11 @@ void GraphController::handleMessage(MessageActivateToken* message)
|
||||
createDummyGraph(message->tokenId, &GraphLayouter::layoutSimpleRing);
|
||||
}
|
||||
|
||||
void GraphController::handleMessage(MessageActivateTokens* message)
|
||||
{
|
||||
createDummyGraph(message->tokenIds[0], &GraphLayouter::layoutSimpleRing);
|
||||
}
|
||||
|
||||
GraphView* GraphController::getView()
|
||||
{
|
||||
return Controller::getView<GraphView>();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "component/controller/GraphLayouter.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateToken.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
|
||||
struct DummyNode;
|
||||
struct DummyEdge;
|
||||
@@ -17,6 +18,7 @@ class GraphAccess;
|
||||
class GraphController
|
||||
: public Controller
|
||||
, public MessageListener<MessageActivateToken>
|
||||
, public MessageListener<MessageActivateTokens>
|
||||
{
|
||||
public:
|
||||
GraphController(GraphAccess* graphAccess);
|
||||
@@ -24,6 +26,8 @@ public:
|
||||
|
||||
private:
|
||||
virtual void handleMessage(MessageActivateToken* message);
|
||||
virtual void handleMessage(MessageActivateTokens* message);
|
||||
|
||||
GraphView* getView();
|
||||
void createDummyGraph(const Id activeId, const LayoutFunction layoutFunction);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "component/view/SearchView.h"
|
||||
#include "data/access/GraphAccess.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
|
||||
SearchController::SearchController(GraphAccess* graphAccess)
|
||||
: m_graphAccess(graphAccess)
|
||||
@@ -15,6 +16,14 @@ SearchController::~SearchController()
|
||||
void SearchController::search(const std::string& s)
|
||||
{
|
||||
LOG_INFO("searching string: \"" + s + "\"");
|
||||
|
||||
std::vector<Id> ids = m_graphAccess->getTokenIdsForQuery(s);
|
||||
if (ids.size())
|
||||
{
|
||||
MessageActivateTokens(ids).dispatch();
|
||||
return;
|
||||
}
|
||||
|
||||
Id nodeId = m_graphAccess->getIdForNodeWithName(s);
|
||||
if (nodeId > 0)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "data/Storage.h"
|
||||
|
||||
#include "data/graph/filter/GraphFilterConductor.h"
|
||||
#include "data/graph/token_component/TokenComponentConst.h"
|
||||
#include "data/graph/token_component/TokenComponentDataType.h"
|
||||
#include "data/graph/token_component/TokenComponentStatic.h"
|
||||
#include "data/graph/SubGraph.h"
|
||||
#include "data/location/TokenLocation.h"
|
||||
#include "data/location/TokenLocationFile.h"
|
||||
#include "data/location/TokenLocationLine.h"
|
||||
@@ -10,6 +12,7 @@
|
||||
#include "data/parser/ParseLocation.h"
|
||||
#include "data/parser/ParseTypeUsage.h"
|
||||
#include "data/parser/ParseVariable.h"
|
||||
#include "data/query/QueryTree.h"
|
||||
#include "data/type/DataType.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/utilityString.h"
|
||||
@@ -525,6 +528,19 @@ std::vector<Id> Storage::getLocationIdsForTokenIds(const std::vector<Id>& tokenI
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Id> Storage::getTokenIdsForQuery(std::string query) const
|
||||
{
|
||||
QueryTree tree(query);
|
||||
GraphFilterConductor conductor;
|
||||
SubGraph outGraph;
|
||||
|
||||
conductor.filter(&tree, &m_graph, &outGraph);
|
||||
|
||||
LOG_INFO_STREAM(<< '\n' << tree << '\n' << outGraph);
|
||||
|
||||
return outGraph.getTokenIds();
|
||||
}
|
||||
|
||||
TokenLocationCollection Storage::getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const
|
||||
{
|
||||
TokenLocationCollection ret;
|
||||
|
||||
@@ -84,6 +84,8 @@ public:
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId) const;
|
||||
virtual std::vector<Id> getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const;
|
||||
|
||||
// LocationAccess implementation
|
||||
virtual TokenLocationCollection getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const;
|
||||
virtual TokenLocationFile getTokenLocationsForFile(const std::string& filePath) const;
|
||||
|
||||
@@ -33,6 +33,8 @@ public:
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId) const = 0;
|
||||
virtual std::vector<Id> getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
||||
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const = 0;
|
||||
};
|
||||
|
||||
#endif // GRAPH_ACCESS_H
|
||||
|
||||
@@ -186,3 +186,13 @@ std::vector<Id> GraphAccessProxy::getLocationIdsForTokenIds(const std::vector<Id
|
||||
|
||||
return std::vector<Id>();
|
||||
}
|
||||
|
||||
std::vector<Id> GraphAccessProxy::getTokenIdsForQuery(std::string query) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getTokenIdsForQuery(query);
|
||||
}
|
||||
|
||||
return std::vector<Id>();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ public:
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId) const;
|
||||
virtual std::vector<Id> getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const;
|
||||
|
||||
private:
|
||||
GraphAccess* m_subject;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
#include "data/query/QueryCommand.h"
|
||||
|
||||
QueryCommand::QueryCommand(const std::string& name)
|
||||
: m_type(COMMAND_INVALID)
|
||||
, m_name(name)
|
||||
{
|
||||
std::map<std::string, CommandType> commandMap = getCommandTypeMap();
|
||||
std::map<std::string, CommandType>::iterator it = commandMap.find(name);
|
||||
|
||||
if (it != commandMap.end())
|
||||
{
|
||||
m_type = it->second;
|
||||
}
|
||||
}
|
||||
|
||||
QueryCommand::~QueryCommand()
|
||||
{
|
||||
}
|
||||
|
||||
bool QueryCommand::isCommand() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryCommand::isOperator() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryCommand::isToken() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryCommand::isComplete() const
|
||||
{
|
||||
return m_type != COMMAND_INVALID;
|
||||
}
|
||||
|
||||
void QueryCommand::print(std::ostream& ostream) const
|
||||
{
|
||||
ostream << m_name;
|
||||
|
||||
if (!isComplete())
|
||||
{
|
||||
ostream << " INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
QueryCommand::CommandType QueryCommand::getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
std::map<std::string, QueryCommand::CommandType> QueryCommand::getCommandTypeMap()
|
||||
{
|
||||
static std::map<std::string, CommandType> commandMap;
|
||||
|
||||
if (commandMap.size())
|
||||
{
|
||||
return commandMap;
|
||||
}
|
||||
|
||||
commandMap.emplace("member", COMMAND_MEMBER);
|
||||
commandMap.emplace("child", COMMAND_MEMBER);
|
||||
|
||||
commandMap.emplace("parent", COMMAND_PARENT);
|
||||
|
||||
commandMap.emplace("function", COMMAND_FUNCTION);
|
||||
commandMap.emplace("variable", COMMAND_GLOBAL_VARIABLE);
|
||||
commandMap.emplace("global", COMMAND_GLOBAL_VARIABLE);
|
||||
commandMap.emplace("class", COMMAND_CLASS);
|
||||
commandMap.emplace("method", COMMAND_METHOD);
|
||||
commandMap.emplace("field", COMMAND_FIELD);
|
||||
commandMap.emplace("namespace", COMMAND_NAMESPACE);
|
||||
commandMap.emplace("struct", COMMAND_STRUCT);
|
||||
commandMap.emplace("enum", COMMAND_ENUM);
|
||||
commandMap.emplace("typedef", COMMAND_TYPEDEF);
|
||||
|
||||
commandMap.emplace("const", COMMAND_CONST);
|
||||
commandMap.emplace("static", COMMAND_STATIC);
|
||||
commandMap.emplace("virtual", COMMAND_VIRTUAL);
|
||||
commandMap.emplace("abstract", COMMAND_PURE_VIRTUAL);
|
||||
commandMap.emplace("pure-virtual", COMMAND_PURE_VIRTUAL);
|
||||
|
||||
commandMap.emplace("public", COMMAND_PUBLIC);
|
||||
commandMap.emplace("protected", COMMAND_PROTECTED);
|
||||
commandMap.emplace("private", COMMAND_PRIVATE);
|
||||
|
||||
commandMap.emplace("caller", COMMAND_CALLER);
|
||||
commandMap.emplace("callee", COMMAND_CALLEE);
|
||||
|
||||
commandMap.emplace("usage", COMMAND_USAGE);
|
||||
|
||||
commandMap.emplace("base", COMMAND_SUPER_CLASS);
|
||||
commandMap.emplace("super", COMMAND_SUPER_CLASS);
|
||||
commandMap.emplace("derived", COMMAND_SUB_CLASS);
|
||||
commandMap.emplace("subclass", COMMAND_SUB_CLASS);
|
||||
|
||||
return commandMap;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef QUERY_COMMAND_H
|
||||
#define QUERY_COMMAND_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "data/query/QueryNode.h"
|
||||
|
||||
class QueryCommand
|
||||
: public QueryNode
|
||||
{
|
||||
public:
|
||||
enum CommandType
|
||||
{
|
||||
COMMAND_INVALID,
|
||||
|
||||
COMMAND_MEMBER,
|
||||
COMMAND_PARENT,
|
||||
COMMAND_FUNCTION,
|
||||
COMMAND_GLOBAL_VARIABLE,
|
||||
COMMAND_CLASS,
|
||||
COMMAND_METHOD,
|
||||
COMMAND_FIELD,
|
||||
COMMAND_NAMESPACE,
|
||||
COMMAND_STRUCT,
|
||||
COMMAND_ENUM,
|
||||
COMMAND_TYPEDEF,
|
||||
|
||||
COMMAND_CONST,
|
||||
COMMAND_STATIC,
|
||||
COMMAND_VIRTUAL,
|
||||
COMMAND_PURE_VIRTUAL,
|
||||
|
||||
COMMAND_PUBLIC,
|
||||
COMMAND_PROTECTED,
|
||||
COMMAND_PRIVATE,
|
||||
|
||||
COMMAND_CALLER,
|
||||
COMMAND_CALLEE,
|
||||
|
||||
COMMAND_USAGE,
|
||||
|
||||
COMMAND_SUPER_CLASS,
|
||||
COMMAND_SUB_CLASS
|
||||
};
|
||||
|
||||
QueryCommand(const std::string& name);
|
||||
~QueryCommand();
|
||||
|
||||
virtual bool isCommand() const;
|
||||
virtual bool isOperator() const;
|
||||
virtual bool isToken() const;
|
||||
|
||||
virtual bool isComplete() const;
|
||||
|
||||
virtual void print(std::ostream& ostream) const;
|
||||
|
||||
CommandType getType() const;
|
||||
|
||||
private:
|
||||
static std::map<std::string, CommandType> getCommandTypeMap();
|
||||
|
||||
CommandType m_type;
|
||||
const std::string m_name;
|
||||
};
|
||||
|
||||
#endif // QUERY_COMMAND_H
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "data/query/QueryNode.h"
|
||||
|
||||
QueryNode::QueryNode()
|
||||
: m_isGroup(false)
|
||||
{
|
||||
}
|
||||
|
||||
QueryNode::~QueryNode()
|
||||
{
|
||||
}
|
||||
|
||||
void QueryNode::print(std::ostream& ostream, int n) const
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
ostream << '\t';
|
||||
}
|
||||
|
||||
if (isGroup())
|
||||
{
|
||||
ostream << '(';
|
||||
}
|
||||
|
||||
print(ostream);
|
||||
|
||||
if (isGroup())
|
||||
{
|
||||
ostream << ')';
|
||||
}
|
||||
|
||||
ostream << '\n';
|
||||
}
|
||||
|
||||
bool QueryNode::isGroup() const
|
||||
{
|
||||
return m_isGroup;
|
||||
}
|
||||
|
||||
void QueryNode::setIsGroup(bool isGroup)
|
||||
{
|
||||
m_isGroup = isGroup;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef QUERY_NODE_H
|
||||
#define QUERY_NODE_H
|
||||
|
||||
#include <ostream>
|
||||
|
||||
class QueryNode
|
||||
{
|
||||
public:
|
||||
QueryNode();
|
||||
virtual ~QueryNode();
|
||||
|
||||
virtual bool isCommand() const = 0;
|
||||
virtual bool isOperator() const = 0;
|
||||
virtual bool isToken() const = 0;
|
||||
|
||||
virtual bool isComplete() const = 0;
|
||||
|
||||
virtual void print(std::ostream& ostream) const = 0;
|
||||
virtual void print(std::ostream& ostream, int n) const;
|
||||
|
||||
bool isGroup() const;
|
||||
void setIsGroup(bool isGroup);
|
||||
|
||||
private:
|
||||
bool m_isGroup;
|
||||
};
|
||||
|
||||
#endif // QUERY_NODE_H
|
||||
@@ -0,0 +1,135 @@
|
||||
#include "data/query/QueryOperator.h"
|
||||
|
||||
const std::map<char, QueryOperator::OperatorType>& QueryOperator::getOperatorTypeMap()
|
||||
{
|
||||
static std::map<char, OperatorType> operatorMap;
|
||||
|
||||
if (operatorMap.size())
|
||||
{
|
||||
return operatorMap;
|
||||
}
|
||||
|
||||
operatorMap.emplace(' ', OPERATOR_NONE);
|
||||
|
||||
operatorMap.emplace('!', OPERATOR_NOT);
|
||||
operatorMap.emplace('.', OPERATOR_SUB);
|
||||
operatorMap.emplace(':', OPERATOR_HAS);
|
||||
operatorMap.emplace('&', OPERATOR_AND);
|
||||
operatorMap.emplace('|', OPERATOR_OR);
|
||||
|
||||
operatorMap.emplace('"', OPERATOR_NAME);
|
||||
operatorMap.emplace('(', OPERATOR_GROUP_OPEN);
|
||||
operatorMap.emplace(')', OPERATOR_GROUP_CLOSE);
|
||||
|
||||
return operatorMap;
|
||||
}
|
||||
|
||||
QueryOperator::OperatorType QueryOperator::getOperatorType(char c)
|
||||
{
|
||||
const std::map<char, OperatorType>& operatorMap = getOperatorTypeMap();
|
||||
std::map<char, OperatorType>::const_iterator it = operatorMap.find(c);
|
||||
|
||||
if (it != operatorMap.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return OPERATOR_NONE;
|
||||
}
|
||||
|
||||
char QueryOperator::getOperator(OperatorType t)
|
||||
{
|
||||
for (const std::pair<char, OperatorType>& p : getOperatorTypeMap())
|
||||
{
|
||||
if (p.second == t)
|
||||
{
|
||||
return p.first;
|
||||
}
|
||||
}
|
||||
|
||||
return '\0';
|
||||
}
|
||||
|
||||
QueryOperator::QueryOperator(OperatorType type)
|
||||
: m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
QueryOperator::~QueryOperator()
|
||||
{
|
||||
}
|
||||
|
||||
bool QueryOperator::isCommand() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryOperator::isOperator() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryOperator::isToken() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryOperator::isComplete() const
|
||||
{
|
||||
if (m_type == OPERATOR_NOT)
|
||||
{
|
||||
return bool(getRight());
|
||||
}
|
||||
|
||||
return getLeft() && getRight();
|
||||
}
|
||||
|
||||
void QueryOperator::print(std::ostream& ostream) const
|
||||
{
|
||||
ostream << m_type;
|
||||
}
|
||||
|
||||
void QueryOperator::print(std::ostream& ostream, int n) const
|
||||
{
|
||||
if (m_left)
|
||||
{
|
||||
m_left->print(ostream, n + 1);
|
||||
}
|
||||
|
||||
QueryNode::print(ostream, n);
|
||||
|
||||
if (m_right)
|
||||
{
|
||||
m_right->print(ostream, n + 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryOperator::getLeft() const
|
||||
{
|
||||
return m_left;
|
||||
}
|
||||
|
||||
void QueryOperator::setLeft(std::shared_ptr<QueryNode> node)
|
||||
{
|
||||
m_left = node;
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryOperator::getRight() const
|
||||
{
|
||||
return m_right;
|
||||
}
|
||||
|
||||
void QueryOperator::setRight(std::shared_ptr<QueryNode> node)
|
||||
{
|
||||
m_right = node;
|
||||
}
|
||||
|
||||
QueryOperator::OperatorType QueryOperator::getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
bool QueryOperator::lowerPrecedence(const QueryOperator& other)
|
||||
{
|
||||
return m_type < other.m_type;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef QUERY_OPERATOR_H
|
||||
#define QUERY_OPERATOR_H
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "data/query/QueryNode.h"
|
||||
|
||||
class QueryOperator
|
||||
: public QueryNode
|
||||
{
|
||||
public:
|
||||
enum OperatorType
|
||||
{
|
||||
OPERATOR_NONE,
|
||||
|
||||
OPERATOR_NOT,
|
||||
OPERATOR_SUB,
|
||||
OPERATOR_HAS,
|
||||
OPERATOR_AND,
|
||||
OPERATOR_OR,
|
||||
|
||||
OPERATOR_NAME,
|
||||
OPERATOR_GROUP_OPEN,
|
||||
OPERATOR_GROUP_CLOSE
|
||||
};
|
||||
|
||||
static const std::map<char, OperatorType>& getOperatorTypeMap();
|
||||
static OperatorType getOperatorType(char c);
|
||||
static char getOperator(OperatorType t);
|
||||
|
||||
QueryOperator(OperatorType type);
|
||||
~QueryOperator();
|
||||
|
||||
virtual bool isCommand() const;
|
||||
virtual bool isOperator() const;
|
||||
virtual bool isToken() const;
|
||||
|
||||
virtual bool isComplete() const;
|
||||
|
||||
virtual void print(std::ostream& ostream) const;
|
||||
virtual void print(std::ostream& ostream, int n) const;
|
||||
|
||||
std::shared_ptr<QueryNode> getLeft() const;
|
||||
void setLeft(std::shared_ptr<QueryNode> node);
|
||||
|
||||
std::shared_ptr<QueryNode> getRight() const;
|
||||
void setRight(std::shared_ptr<QueryNode> node);
|
||||
|
||||
OperatorType getType() const;
|
||||
|
||||
bool lowerPrecedence(const QueryOperator& other);
|
||||
|
||||
private:
|
||||
std::shared_ptr<QueryNode> m_left;
|
||||
std::shared_ptr<QueryNode> m_right;
|
||||
|
||||
const OperatorType m_type;
|
||||
};
|
||||
|
||||
#endif // QUERY_OPERATOR_H
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "data/query/QueryToken.h"
|
||||
|
||||
QueryToken::QueryToken(const std::string& name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
QueryToken::~QueryToken()
|
||||
{
|
||||
}
|
||||
|
||||
bool QueryToken::isCommand() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryToken::isOperator() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryToken::isToken() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryToken::isComplete() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void QueryToken::print(std::ostream& ostream) const
|
||||
{
|
||||
ostream << '"' << m_name << '"';
|
||||
}
|
||||
|
||||
const std::string& QueryToken::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef QUERY_TOKEN_H
|
||||
#define QUERY_TOKEN_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "data/query/QueryNode.h"
|
||||
|
||||
class QueryToken
|
||||
: public QueryNode
|
||||
{
|
||||
public:
|
||||
QueryToken(const std::string& name);
|
||||
~QueryToken();
|
||||
|
||||
virtual bool isCommand() const;
|
||||
virtual bool isOperator() const;
|
||||
virtual bool isToken() const;
|
||||
virtual bool isComplete() const;
|
||||
|
||||
virtual void print(std::ostream& ostream) const;
|
||||
|
||||
const std::string& getName() const;
|
||||
|
||||
private:
|
||||
const std::string m_name;
|
||||
};
|
||||
|
||||
#endif // QUERY_TOKEN_H
|
||||
@@ -0,0 +1,207 @@
|
||||
#include "data/query/QueryTree.h"
|
||||
|
||||
#include "data/query/QueryCommand.h"
|
||||
#include "data/query/QueryNode.h"
|
||||
#include "data/query/QueryOperator.h"
|
||||
#include "data/query/QueryToken.h"
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
QueryTree::QueryTree(std::string query)
|
||||
: m_valid(true)
|
||||
{
|
||||
std::deque<std::string> tokens =
|
||||
utility::split<std::deque<std::string>>(query, QueryOperator::getOperator(QueryOperator::OPERATOR_NONE));
|
||||
|
||||
for (const std::pair<char, QueryOperator::OperatorType>& p : QueryOperator::getOperatorTypeMap())
|
||||
{
|
||||
tokens = utility::tokenize<std::deque<std::string>>(tokens, p.first);
|
||||
}
|
||||
|
||||
for (std::string str : tokens)
|
||||
{
|
||||
m_query += str + ' ';
|
||||
}
|
||||
|
||||
m_root = buildTree(tokens, nullptr);
|
||||
}
|
||||
|
||||
QueryTree::~QueryTree()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryTree::getRoot() const
|
||||
{
|
||||
return m_root;
|
||||
}
|
||||
|
||||
bool QueryTree::isValid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
void QueryTree::print(std::ostream& ostream) const
|
||||
{
|
||||
ostream << m_query;
|
||||
|
||||
if (!m_valid)
|
||||
{
|
||||
ostream << " INVALID";
|
||||
}
|
||||
|
||||
ostream << '\n';
|
||||
|
||||
if (m_root)
|
||||
{
|
||||
m_root->print(ostream, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryTree::buildTree(std::deque<std::string>& tokens, std::shared_ptr<QueryNode> frontNode)
|
||||
{
|
||||
std::shared_ptr<QueryNode> node = getNextNode(tokens);
|
||||
std::shared_ptr<QueryOperator> operatorNode = std::dynamic_pointer_cast<QueryOperator>(node);
|
||||
|
||||
if (frontNode)
|
||||
{
|
||||
if (node->isComplete())
|
||||
{
|
||||
std::shared_ptr<QueryOperator> subNode = std::make_shared<QueryOperator>(QueryOperator::OPERATOR_SUB);
|
||||
subNode->setLeft(frontNode);
|
||||
subNode->setRight(node);
|
||||
node = subNode;
|
||||
}
|
||||
else if (node->isOperator() && operatorNode)
|
||||
{
|
||||
operatorNode->setLeft(frontNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (tokens.size())
|
||||
{
|
||||
if (node->isComplete())
|
||||
{
|
||||
node = buildTree(tokens, node);
|
||||
}
|
||||
else if (node->isOperator() && operatorNode)
|
||||
{
|
||||
std::shared_ptr<QueryNode> rightNode = buildTree(tokens, nullptr);
|
||||
std::shared_ptr<QueryOperator> rightOperatorNode = std::dynamic_pointer_cast<QueryOperator>(rightNode);
|
||||
|
||||
if (rightNode->isOperator() && !rightNode->isGroup() &&
|
||||
operatorNode->lowerPrecedence(*rightOperatorNode.get()))
|
||||
{
|
||||
operatorNode->setRight(rightOperatorNode->getLeft());
|
||||
rightOperatorNode->setLeft(operatorNode);
|
||||
node = rightNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
operatorNode->setRight(rightNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!node->isComplete())
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryTree::buildGroup(std::deque<std::string>& tokens, QueryOperator::OperatorType closeType)
|
||||
{
|
||||
std::deque<std::string> group;
|
||||
std::string name;
|
||||
char delimiter = QueryOperator::getOperator(closeType);
|
||||
while (tokens.front() != std::string(1, delimiter) && tokens.size())
|
||||
{
|
||||
group.push_back(tokens.front());
|
||||
name += tokens.front();
|
||||
tokens.pop_front();
|
||||
}
|
||||
|
||||
if (tokens.size())
|
||||
{
|
||||
tokens.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
if (!group.size())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (closeType == QueryOperator::OPERATOR_NAME)
|
||||
{
|
||||
return std::make_shared<QueryToken>(name);
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> groupNode = buildTree(group, nullptr);
|
||||
groupNode->setIsGroup(true);
|
||||
|
||||
return groupNode;
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryTree::getNextNode(std::deque<std::string>& tokens)
|
||||
{
|
||||
while (tokens.size())
|
||||
{
|
||||
std::string token = tokens.front();
|
||||
tokens.pop_front();
|
||||
|
||||
QueryOperator::OperatorType type = QueryOperator::getOperatorType(token[0]);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case QueryOperator::OPERATOR_NOT:
|
||||
case QueryOperator::OPERATOR_SUB:
|
||||
case QueryOperator::OPERATOR_HAS:
|
||||
case QueryOperator::OPERATOR_AND:
|
||||
case QueryOperator::OPERATOR_OR:
|
||||
return std::make_shared<QueryOperator>(type);
|
||||
|
||||
case QueryOperator::OPERATOR_NAME:
|
||||
return buildGroup(tokens, QueryOperator::OPERATOR_NAME);
|
||||
case QueryOperator::OPERATOR_GROUP_OPEN:
|
||||
return buildGroup(tokens, QueryOperator::OPERATOR_GROUP_CLOSE);
|
||||
case QueryOperator::OPERATOR_GROUP_CLOSE:
|
||||
m_valid = false;
|
||||
break;
|
||||
|
||||
case QueryOperator::OPERATOR_NONE:
|
||||
return createCommand(token);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<QueryNode> QueryTree::createCommand(std::string name)
|
||||
{
|
||||
std::shared_ptr<QueryCommand> node = std::make_shared<QueryCommand>(name);
|
||||
|
||||
if (node->getType() == QueryCommand::COMMAND_INVALID)
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& ostream, const QueryTree& tree)
|
||||
{
|
||||
tree.print(ostream);
|
||||
return ostream;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef QUERY_TREE_H
|
||||
#define QUERY_TREE_H
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include "data/query/QueryOperator.h"
|
||||
|
||||
class QueryNode;
|
||||
|
||||
class QueryTree
|
||||
{
|
||||
public:
|
||||
QueryTree(std::string query);
|
||||
~QueryTree();
|
||||
|
||||
std::shared_ptr<QueryNode> getRoot() const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
void print(std::ostream& ostream) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<QueryNode> buildTree(std::deque<std::string>& tokens, std::shared_ptr<QueryNode> frontNode);
|
||||
std::shared_ptr<QueryNode> buildGroup(std::deque<std::string>& tokens, QueryOperator::OperatorType closeType);
|
||||
std::shared_ptr<QueryNode> getNextNode(std::deque<std::string>& tokens);
|
||||
std::shared_ptr<QueryNode> createCommand(std::string name);
|
||||
|
||||
std::shared_ptr<QueryNode> m_root;
|
||||
std::string m_query;
|
||||
bool m_valid;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& ostream, const QueryTree& tree);
|
||||
|
||||
#endif // QUERY_TREE_H
|
||||
@@ -12,7 +12,7 @@ DataType::DataType(const std::string& typeName, const DataTypeQualifierList& qua
|
||||
}
|
||||
|
||||
DataType::DataType(
|
||||
const std::string& typeName, const DataTypeQualifierList& qualifierList, const DataTypeModifierStack& modifierStack
|
||||
const std::string& typeName, const DataTypeQualifierList& qualifierList, const DataTypeModifierStack& modifierStack
|
||||
)
|
||||
: m_typeName(typeName)
|
||||
, m_qualifierList(qualifierList)
|
||||
|
||||
@@ -20,4 +20,4 @@ public:
|
||||
const Id tokenId;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_ACTIVATE_TOKEN_LOCATION_H
|
||||
#endif // MESSAGE_ACTIVATE_TOKEN_H
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef MESSAGE_ACTIVATE_TOKENS_H
|
||||
#define MESSAGE_ACTIVATE_TOKENS_H
|
||||
|
||||
#include "utility/messaging/Message.h"
|
||||
#include "utility/types.h"
|
||||
|
||||
class MessageActivateTokens: public Message<MessageActivateTokens>
|
||||
{
|
||||
public:
|
||||
MessageActivateTokens(const std::vector<Id>& tokenIds)
|
||||
: tokenIds(tokenIds)
|
||||
{
|
||||
}
|
||||
|
||||
static const std::string getStaticType()
|
||||
{
|
||||
return "MessageActivateTokens";
|
||||
}
|
||||
|
||||
const std::vector<Id> tokenIds;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_ACTIVATE_TOKENS_H
|
||||
@@ -12,6 +12,18 @@ namespace utility
|
||||
template<typename ContainerType>
|
||||
ContainerType split(const std::string& str, const std::string& delimiter);
|
||||
|
||||
template<typename ContainerType>
|
||||
ContainerType tokenize(const std::string& str, char delimiter);
|
||||
|
||||
template<typename ContainerType>
|
||||
ContainerType tokenize(const std::string& str, const std::string& delimiter);
|
||||
|
||||
template<typename ContainerType>
|
||||
ContainerType tokenize(const ContainerType& list, char delimiter);
|
||||
|
||||
template<typename ContainerType>
|
||||
ContainerType tokenize(const ContainerType& list, const std::string& delimiter);
|
||||
|
||||
std::string substrAfter(const std::string& str, char delimiter);
|
||||
|
||||
bool isPrefix(const std::string& prefix, const std::string& text);
|
||||
@@ -41,4 +53,58 @@ ContainerType utility::split(const std::string& str, const std::string& delimite
|
||||
return c;
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
ContainerType utility::tokenize(const std::string& str, char delimiter)
|
||||
{
|
||||
return tokenize<ContainerType>(str, std::string(1, delimiter));
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
ContainerType utility::tokenize(const std::string& str, const std::string& delimiter)
|
||||
{
|
||||
size_t pos = 0;
|
||||
size_t oldPos = 0;
|
||||
ContainerType c;
|
||||
|
||||
do
|
||||
{
|
||||
pos = str.find(delimiter, oldPos);
|
||||
|
||||
if (pos != oldPos)
|
||||
{
|
||||
c.push_back(str.substr(oldPos, pos - oldPos));
|
||||
}
|
||||
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
c.push_back(str.substr(pos, delimiter.size()));
|
||||
}
|
||||
|
||||
oldPos = pos + delimiter.size();
|
||||
}
|
||||
while (pos != std::string::npos && oldPos < str.size());
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
ContainerType utility::tokenize(const ContainerType& list, char delimiter)
|
||||
{
|
||||
return tokenize<ContainerType>(list, std::string(1, delimiter));
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
ContainerType utility::tokenize(const ContainerType& list, const std::string& delimiter)
|
||||
{
|
||||
ContainerType c;
|
||||
|
||||
for (std::string str : list)
|
||||
{
|
||||
ContainerType c2 = tokenize<ContainerType>(str, delimiter);
|
||||
c.insert(c.end(), c2.begin(), c2.end());
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif // UTILITY_STRING_H
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
add_files(
|
||||
TEST_FILES
|
||||
|
||||
TestSuiteFixture.cpp
|
||||
TestSuiteFixture.h
|
||||
|
||||
ConfigManagerTestSuite.h
|
||||
CxxParserTestSuite.h
|
||||
DataTypeTestSuite.h
|
||||
@@ -10,8 +13,6 @@ add_files(
|
||||
MessageQueueTestSuite.h
|
||||
SettingsTestSuite.h
|
||||
StorageTestSuite.h
|
||||
TestSuiteFixture.cpp
|
||||
TestSuiteFixture.h
|
||||
TextAccessTestSuite.h
|
||||
TokenLocationCollectionTestSuite.h
|
||||
UtilityStringTestSuite.h
|
||||
|
||||
@@ -51,6 +51,71 @@ public:
|
||||
TS_ASSERT_EQUALS(result[3], "C");
|
||||
}
|
||||
|
||||
void test_split_with_delimiter_at_start()
|
||||
{
|
||||
std::vector<std::string> result = utility::split<std::vector<std::string> >(":B:C", ':');
|
||||
|
||||
TS_ASSERT_EQUALS(result.size(), 3);
|
||||
TS_ASSERT_EQUALS(result[0], "");
|
||||
TS_ASSERT_EQUALS(result[1], "B");
|
||||
TS_ASSERT_EQUALS(result[2], "C");
|
||||
}
|
||||
|
||||
void test_split_with_delimiter_at_end()
|
||||
{
|
||||
std::vector<std::string> result = utility::split<std::vector<std::string> >("B:C:", ':');
|
||||
|
||||
TS_ASSERT_EQUALS(result.size(), 3);
|
||||
TS_ASSERT_EQUALS(result[0], "B");
|
||||
TS_ASSERT_EQUALS(result[1], "C");
|
||||
TS_ASSERT_EQUALS(result[2], "");
|
||||
}
|
||||
|
||||
void test_tokenize_with_string()
|
||||
{
|
||||
std::vector<std::string> result = utility::tokenize<std::vector<std::string> >("A->B->C", "->");
|
||||
|
||||
TS_ASSERT_EQUALS(result.size(), 5);
|
||||
TS_ASSERT_EQUALS(result[0], "A");
|
||||
TS_ASSERT_EQUALS(result[1], "->");
|
||||
TS_ASSERT_EQUALS(result[2], "B");
|
||||
TS_ASSERT_EQUALS(result[3], "->");
|
||||
TS_ASSERT_EQUALS(result[4], "C");
|
||||
}
|
||||
|
||||
void test_tokenize_with_string_and_delimiter_at_start()
|
||||
{
|
||||
std::vector<std::string> result = utility::tokenize<std::vector<std::string> >("->B", "->");
|
||||
|
||||
TS_ASSERT_EQUALS(result.size(), 2);
|
||||
TS_ASSERT_EQUALS(result[0], "->");
|
||||
TS_ASSERT_EQUALS(result[1], "B");
|
||||
}
|
||||
|
||||
void test_tokenize_with_string_and_delimiter_at_end()
|
||||
{
|
||||
std::vector<std::string> result = utility::tokenize<std::vector<std::string> >("C+", '+');
|
||||
|
||||
TS_ASSERT_EQUALS(result.size(), 2);
|
||||
TS_ASSERT_EQUALS(result[0], "C");
|
||||
TS_ASSERT_EQUALS(result[1], "+");
|
||||
}
|
||||
|
||||
void test_tokenize_with_vector()
|
||||
{
|
||||
std::vector<std::string> result = utility::tokenize<std::vector<std::string> >("A->B=C->D", "->");
|
||||
result = utility::tokenize<std::vector<std::string>>(result, "=");
|
||||
|
||||
TS_ASSERT_EQUALS(result.size(), 7);
|
||||
TS_ASSERT_EQUALS(result[0], "A");
|
||||
TS_ASSERT_EQUALS(result[1], "->");
|
||||
TS_ASSERT_EQUALS(result[2], "B");
|
||||
TS_ASSERT_EQUALS(result[3], "=");
|
||||
TS_ASSERT_EQUALS(result[4], "C");
|
||||
TS_ASSERT_EQUALS(result[5], "->");
|
||||
TS_ASSERT_EQUALS(result[6], "D");
|
||||
}
|
||||
|
||||
void test_substr_after_with_single_delimiter_occurence()
|
||||
{
|
||||
TS_ASSERT_EQUALS(utility::substrAfter("foo bar", ' '), "bar");
|
||||
|
||||
Reference in New Issue
Block a user