logic: Only request unconnected child nodes when expanding node
* increases graph performance by ~30%
This commit is contained in:
@@ -268,44 +268,73 @@ void GraphController::handleMessage(MessageGraphNodeExpand* message)
|
||||
return;
|
||||
}
|
||||
|
||||
DummyNode* node = getDummyGraphNodeById(message->tokenId);
|
||||
if (node)
|
||||
Id nodeId = message->tokenId;
|
||||
DummyNode* dummyNode = getDummyGraphNodeById(nodeId);
|
||||
if (dummyNode)
|
||||
{
|
||||
if (!node->active && message->expand)
|
||||
dummyNode->expanded = message->expand;
|
||||
|
||||
if (message->expand && dummyNode->hasMissingChildNodes())
|
||||
{
|
||||
for (size_t i = 0, l = m_dummyEdges.size(); i < l; i++)
|
||||
{
|
||||
std::shared_ptr<DummyEdge> edge = m_dummyEdges[i];
|
||||
std::shared_ptr<Graph> childGraph = m_storageAccess->getGraphForChildrenOfNodeId(nodeId);
|
||||
|
||||
if (edge && edge->data && edge->data->isType(Edge::EDGE_AGGREGATION) &&
|
||||
(edge->targetId == node->tokenId || edge->ownerId == node->tokenId))
|
||||
childGraph->getNodeById(nodeId)->forEachEdgeOfType(Edge::EDGE_MEMBER,
|
||||
[this](Edge* edge)
|
||||
{
|
||||
std::vector<Id> aggregationIds =
|
||||
utility::toVector<Id>(edge->data->getComponent<TokenComponentAggregation>()->getAggregationIds());
|
||||
m_graph->addEdgeAsPlainCopy(edge);
|
||||
}
|
||||
);
|
||||
|
||||
if (m_graph->getEdgeById(aggregationIds[0]) != nullptr)
|
||||
Node* node = m_graph->getNodeById(nodeId);
|
||||
std::vector<std::shared_ptr<DummyNode>> newDummyNodes = createDummyNodeTopDown(node, node->getLastParentNode()->getId());
|
||||
if (newDummyNodes.size() != 1)
|
||||
{
|
||||
LOG_ERROR("Wrong amount of dummy nodes created");
|
||||
return;
|
||||
}
|
||||
std::shared_ptr<DummyNode> newDummyNode = newDummyNodes[0];
|
||||
|
||||
// replace newer dummy graph nodes with the old ones. Nodes will have the correct sorting after that.
|
||||
newDummyNode->replaceSubGraphNodes(dummyNode->getSubGraphNodes());
|
||||
|
||||
// move all newer and older dummy graph nodes into the old dummy node
|
||||
dummyNode->replaceAccessNodes(newDummyNode->getAccessNodes());
|
||||
|
||||
|
||||
if (!dummyNode->active && message->expand)
|
||||
{
|
||||
for (size_t i = 0, l = m_dummyEdges.size(); i < l; i++)
|
||||
{
|
||||
std::shared_ptr<DummyEdge> edge = m_dummyEdges[i];
|
||||
|
||||
if (edge && edge->data && edge->data->isType(Edge::EDGE_AGGREGATION) &&
|
||||
(edge->targetId == dummyNode->tokenId || edge->ownerId == dummyNode->tokenId))
|
||||
{
|
||||
break;
|
||||
}
|
||||
std::vector<Id> aggregationIds =
|
||||
utility::toVector<Id>(edge->data->getComponent<TokenComponentAggregation>()->getAggregationIds());
|
||||
|
||||
std::shared_ptr<Graph> graph = m_storageAccess->getGraphForActiveTokenIds(aggregationIds);
|
||||
|
||||
graph->forEachEdge(
|
||||
[this](Edge* e)
|
||||
if (m_graph->getEdgeById(aggregationIds[0]) != nullptr)
|
||||
{
|
||||
if (!e->isType(Edge::EDGE_MEMBER))
|
||||
{
|
||||
m_dummyEdges.push_back(std::make_shared<DummyEdge>(
|
||||
e->getFrom()->getId(), e->getTo()->getId(), m_graph->addEdgeAsPlainCopy(e)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
);
|
||||
|
||||
std::shared_ptr<Graph> aggregationGraph = m_storageAccess->getGraphForActiveTokenIds(aggregationIds);
|
||||
|
||||
aggregationGraph->forEachEdge(
|
||||
[this](Edge* e)
|
||||
{
|
||||
if (!e->isType(Edge::EDGE_MEMBER))
|
||||
{
|
||||
m_dummyEdges.push_back(std::make_shared<DummyEdge>(
|
||||
e->getFrom()->getId(), e->getTo()->getId(), m_graph->addEdgeAsPlainCopy(e)));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node->expanded = message->expand;
|
||||
|
||||
setActiveAndVisibility(utility::concat(m_activeNodeIds, m_activeEdgeIds));
|
||||
|
||||
layoutNesting();
|
||||
@@ -616,8 +645,6 @@ void GraphController::setVisibility(bool noActive)
|
||||
|
||||
for (std::shared_ptr<DummyNode> node : m_dummyNodes)
|
||||
{
|
||||
removeImplicitChildrenRecursive(node.get());
|
||||
|
||||
setNodeVisibilityRecursiveBottomUp(node.get(), noActive);
|
||||
}
|
||||
}
|
||||
@@ -649,41 +676,6 @@ void GraphController::setNodeActiveRecursive(DummyNode* node, const std::vector<
|
||||
}
|
||||
}
|
||||
|
||||
void GraphController::removeImplicitChildrenRecursive(DummyNode* node)
|
||||
{
|
||||
if (node->isGraphNode() && !node->data->isExplicit())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < node->subNodes.size(); i++)
|
||||
{
|
||||
bool removeNode = false;
|
||||
|
||||
DummyNode* subNode = node->subNodes[i].get();
|
||||
if (subNode->isGraphNode() && subNode->data->isImplicit() &&
|
||||
!subNode->connected && !subNode->active && !subNode->subNodes.size())
|
||||
{
|
||||
removeNode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
removeImplicitChildrenRecursive(subNode);
|
||||
|
||||
if (subNode->isAccessNode() && subNode->subNodes.size() == 0)
|
||||
{
|
||||
removeNode = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeNode)
|
||||
{
|
||||
node->subNodes.erase(node->subNodes.begin() + i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphController::setNodeVisibilityRecursiveBottomUp(DummyNode* node, bool noActive) const
|
||||
{
|
||||
node->visible = false;
|
||||
@@ -1310,8 +1302,10 @@ void GraphController::layoutNestingRecursive(DummyNode* node) const
|
||||
|
||||
width = margins.charWidth * node->name.size();
|
||||
|
||||
if (node->data->isType(Node::NODE_TYPE | Node::NODE_BUILTIN_TYPE | Node::NODE_CLASS | Node::NODE_STRUCT | Node::NODE_ENUM) &&
|
||||
node->subNodes.size())
|
||||
Node::NodeTypeMask mask =
|
||||
Node::NODE_NON_INDEXED | Node::NODE_TYPE | Node::NODE_BUILTIN_TYPE |
|
||||
Node::NODE_CLASS | Node::NODE_STRUCT | Node::NODE_ENUM;
|
||||
if (node->data->isType(mask) && node->data->getChildCount() > 0)
|
||||
{
|
||||
addExpandToggleNode(node);
|
||||
}
|
||||
@@ -1417,7 +1411,7 @@ void GraphController::addExpandToggleNode(DummyNode* node) const
|
||||
expandNode->visible = true;
|
||||
expandNode->expanded = node->expanded;
|
||||
|
||||
bool hasVisibleSubNode = false;
|
||||
size_t visibleSubNodeCount = 0;
|
||||
for (size_t i = 0; i < node->subNodes.size(); i++)
|
||||
{
|
||||
DummyNode* subNode = node->subNodes[i].get();
|
||||
@@ -1436,18 +1430,15 @@ void GraphController::addExpandToggleNode(DummyNode* node) const
|
||||
|
||||
for (std::shared_ptr<DummyNode> subSubNode : subNode->subNodes)
|
||||
{
|
||||
if (!subSubNode->visible)
|
||||
if (subSubNode->visible && (!subSubNode->isGraphNode() || !subSubNode->data->isImplicit()))
|
||||
{
|
||||
expandNode->invisibleSubNodeCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasVisibleSubNode = true;
|
||||
visibleSubNodeCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((expandNode->isExpanded() && hasVisibleSubNode) || expandNode->invisibleSubNodeCount)
|
||||
expandNode->invisibleSubNodeCount = node->data->getChildCount() - visibleSubNodeCount;
|
||||
if ((expandNode->isExpanded() && visibleSubNodeCount > 0) || expandNode->invisibleSubNodeCount)
|
||||
{
|
||||
node->subNodes.push_back(expandNode);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,6 @@ private:
|
||||
void setVisibility(bool noActive);
|
||||
void setActiveAndVisibility(const std::vector<Id>& activeTokenIds);
|
||||
void setNodeActiveRecursive(DummyNode* node, const std::vector<Id>& activeTokenIds, bool* noActive) const;
|
||||
void removeImplicitChildrenRecursive(DummyNode* node);
|
||||
bool setNodeVisibilityRecursiveBottomUp(DummyNode* node, bool noActive) const;
|
||||
void setNodeVisibilityRecursiveTopDown(DummyNode* node, bool parentExpanded) const;
|
||||
|
||||
|
||||
@@ -238,6 +238,104 @@ public:
|
||||
return bundleId;
|
||||
}
|
||||
|
||||
bool hasMissingChildNodes() const
|
||||
{
|
||||
size_t childCount = 0;
|
||||
if (isGraphNode())
|
||||
{
|
||||
childCount = data->getChildCount();
|
||||
}
|
||||
|
||||
size_t subNodeCount = 0;
|
||||
for (std::shared_ptr<DummyNode> subNode : subNodes)
|
||||
{
|
||||
if (subNode->isAccessNode())
|
||||
{
|
||||
for (std::shared_ptr<DummyNode> subSubNode : subNode->subNodes)
|
||||
{
|
||||
if (subSubNode->isGraphNode() && !subSubNode->data->isImplicit())
|
||||
{
|
||||
subNodeCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return subNodeCount < childCount;
|
||||
}
|
||||
|
||||
std::map<Id, std::shared_ptr<DummyNode>> getSubGraphNodes() const
|
||||
{
|
||||
std::map<Id, std::shared_ptr<DummyNode>> subGraphNodes;
|
||||
|
||||
for (std::shared_ptr<DummyNode> subNode : subNodes)
|
||||
{
|
||||
if (subNode->isAccessNode())
|
||||
{
|
||||
for (std::shared_ptr<DummyNode> subSubNode : subNode->subNodes)
|
||||
{
|
||||
if (subSubNode->isGraphNode())
|
||||
{
|
||||
subGraphNodes.emplace(subSubNode->tokenId, subSubNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return subGraphNodes;
|
||||
}
|
||||
|
||||
void replaceSubGraphNodes(std::map<Id, std::shared_ptr<DummyNode>> subGraphNodes) const
|
||||
{
|
||||
for (std::shared_ptr<DummyNode> subNode : subNodes)
|
||||
{
|
||||
if (subNode->isAccessNode())
|
||||
{
|
||||
for (size_t i = 0; i < subNode->subNodes.size(); i++)
|
||||
{
|
||||
std::shared_ptr<DummyNode> subSubNode = subNode->subNodes[i];
|
||||
if (!subSubNode->isGraphNode())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = subGraphNodes.find(subSubNode->tokenId);
|
||||
if (it != subGraphNodes.end())
|
||||
{
|
||||
subNode->subNodes[i] = it->second;
|
||||
subGraphNodes.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<DummyNode>> getAccessNodes() const
|
||||
{
|
||||
std::vector<std::shared_ptr<DummyNode>> accessNodes;
|
||||
for (std::shared_ptr<DummyNode> subNode : subNodes)
|
||||
{
|
||||
if (subNode->isAccessNode())
|
||||
{
|
||||
accessNodes.push_back(subNode);
|
||||
}
|
||||
}
|
||||
return accessNodes;
|
||||
}
|
||||
|
||||
void replaceAccessNodes(const std::vector<std::shared_ptr<DummyNode>>& accessNodes)
|
||||
{
|
||||
for (size_t i = 0; i < subNodes.size(); i++)
|
||||
{
|
||||
if (subNodes[i]->isAccessNode())
|
||||
{
|
||||
subNodes.erase(subNodes.begin() + i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
subNodes.insert(subNodes.end(), accessNodes.begin(), accessNodes.end());
|
||||
}
|
||||
|
||||
Vec2i position;
|
||||
Vec2i size;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ HierarchyCache::HierarchyNode::HierarchyNode(Id nodeId)
|
||||
, m_edgeId(0)
|
||||
, m_parent(nullptr)
|
||||
, m_isVisible(true)
|
||||
, m_isIndexed(true)
|
||||
, m_isImplicit(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -39,25 +39,33 @@ void HierarchyCache::HierarchyNode::addChild(HierarchyNode* child)
|
||||
m_children.push_back(child);
|
||||
}
|
||||
|
||||
const std::vector<HierarchyCache::HierarchyNode*>& HierarchyCache::HierarchyNode::getChildren() const
|
||||
size_t HierarchyCache::HierarchyNode::getChildrenCount() const
|
||||
{
|
||||
return m_children;
|
||||
return m_children.size();
|
||||
}
|
||||
|
||||
void HierarchyCache::HierarchyNode::addChildIds(std::vector<Id>* nodeIds) const
|
||||
size_t HierarchyCache::HierarchyNode::getNonImplicitChildrenCount() const
|
||||
{
|
||||
size_t count = 0;
|
||||
for (const HierarchyNode* child : m_children)
|
||||
{
|
||||
nodeIds->push_back(child->getNodeId());
|
||||
if (!child->isImplicit())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void HierarchyCache::HierarchyNode::addChildIds(std::set<Id>* nodeIds, std::set<Id>* edgeIds) const
|
||||
void HierarchyCache::HierarchyNode::addNonImplicitChildIds(std::vector<Id>* nodeIds, std::vector<Id>* edgeIds) const
|
||||
{
|
||||
for (const HierarchyNode* child : m_children)
|
||||
{
|
||||
nodeIds->insert(child->getNodeId());
|
||||
edgeIds->insert(child->getEdgeId());
|
||||
if (!child->isImplicit())
|
||||
{
|
||||
nodeIds->push_back(child->getNodeId());
|
||||
edgeIds->push_back(child->getEdgeId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,21 +80,6 @@ void HierarchyCache::HierarchyNode::addChildIdsRecursive(std::set<Id>* nodeIds,
|
||||
}
|
||||
}
|
||||
|
||||
void HierarchyCache::HierarchyNode::addVisibleNodeIdsRecursive(std::vector<Id>* nodeIds) const
|
||||
{
|
||||
if (isVisible())
|
||||
{
|
||||
nodeIds->push_back(getNodeId());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const HierarchyNode* child : m_children)
|
||||
{
|
||||
child->addVisibleNodeIdsRecursive(nodeIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HierarchyCache::HierarchyNode::isVisible() const
|
||||
{
|
||||
return m_isVisible;
|
||||
@@ -97,14 +90,14 @@ void HierarchyCache::HierarchyNode::setIsVisible(bool isVisible)
|
||||
m_isVisible = isVisible;
|
||||
}
|
||||
|
||||
bool HierarchyCache::HierarchyNode::isIndexed() const
|
||||
bool HierarchyCache::HierarchyNode::isImplicit() const
|
||||
{
|
||||
return m_isIndexed;
|
||||
return m_isImplicit;
|
||||
}
|
||||
|
||||
void HierarchyCache::HierarchyNode::setIsIndexed(bool isIndexed)
|
||||
void HierarchyCache::HierarchyNode::setIsImplicit(bool isImplicit)
|
||||
{
|
||||
m_isIndexed = isIndexed;
|
||||
m_isImplicit = isImplicit;
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +106,7 @@ void HierarchyCache::clear()
|
||||
m_nodes.clear();
|
||||
}
|
||||
|
||||
void HierarchyCache::createConnection(Id edgeId, Id fromId, Id toId, bool sourceVisible, bool sourceIndexed, bool targetIndexed)
|
||||
void HierarchyCache::createConnection(Id edgeId, Id fromId, Id toId, bool sourceVisible, bool targetImplicit)
|
||||
{
|
||||
HierarchyNode* from = createNode(fromId);
|
||||
HierarchyNode* to = createNode(toId);
|
||||
@@ -122,10 +115,9 @@ void HierarchyCache::createConnection(Id edgeId, Id fromId, Id toId, bool source
|
||||
to->setParent(from);
|
||||
|
||||
from->setIsVisible(sourceVisible);
|
||||
from->setIsIndexed(sourceIndexed);
|
||||
|
||||
to->setEdgeId(edgeId);
|
||||
to->setIsIndexed(targetIndexed);
|
||||
to->setIsImplicit(targetImplicit);
|
||||
}
|
||||
|
||||
Id HierarchyCache::getLastVisibleParentNodeId(Id nodeId) const
|
||||
@@ -170,23 +162,9 @@ size_t HierarchyCache::getIndexOfLastVisibleParentNode(Id nodeId) const
|
||||
return idx;
|
||||
}
|
||||
|
||||
void HierarchyCache::addAllChildIdsForNodeId(Id nodeId, std::set<Id>* nodeIds, std::set<Id>* edgeIds) const
|
||||
void HierarchyCache::addAllVisibleParentIdsForNodeId(Id nodeId, std::set<Id>* nodeIds, std::set<Id>* edgeIds) const
|
||||
{
|
||||
HierarchyNode* node = getNode(nodeId);
|
||||
if (node && node->isVisible())
|
||||
{
|
||||
node->addChildIdsRecursive(nodeIds, edgeIds);
|
||||
}
|
||||
}
|
||||
|
||||
void HierarchyCache::addAllVisibleParentsAndChildIdsForNodeId(Id nodeId, std::set<Id>* nodeIds, std::set<Id>* edgeIds) const
|
||||
{
|
||||
HierarchyNode* node = getNode(nodeId);
|
||||
if (node && node->isVisible())
|
||||
{
|
||||
node->addChildIds(nodeIds, edgeIds);
|
||||
}
|
||||
|
||||
Id edgeId = 0;
|
||||
while (node && node->isVisible())
|
||||
{
|
||||
@@ -202,26 +180,32 @@ void HierarchyCache::addAllVisibleParentsAndChildIdsForNodeId(Id nodeId, std::se
|
||||
}
|
||||
}
|
||||
|
||||
void HierarchyCache::addFirstChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds) const
|
||||
void HierarchyCache::addAllChildIdsForNodeId(Id nodeId, std::set<Id>* nodeIds, std::set<Id>* edgeIds) const
|
||||
{
|
||||
HierarchyNode* node = getNode(nodeId);
|
||||
if (node)
|
||||
if (node && node->isVisible())
|
||||
{
|
||||
node->addChildIds(nodeIds);
|
||||
node->addChildIdsRecursive(nodeIds, edgeIds);
|
||||
}
|
||||
}
|
||||
|
||||
void HierarchyCache::addFirstVisibleChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds) const
|
||||
void HierarchyCache::addFirstNonImplicitChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds, std::vector<Id>* edgeIds) const
|
||||
{
|
||||
HierarchyNode* node = getNode(nodeId);
|
||||
if (node)
|
||||
{
|
||||
node->addVisibleNodeIdsRecursive(nodeIds);
|
||||
node->addNonImplicitChildIds(nodeIds, edgeIds);
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
size_t HierarchyCache::getFirstNonImplicitChildIdsCountForNodeId(Id nodeId) const
|
||||
{
|
||||
HierarchyNode* node = getNode(nodeId);
|
||||
if (node)
|
||||
{
|
||||
nodeIds->push_back(nodeId);
|
||||
return node->getNonImplicitChildrenCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool HierarchyCache::isChildOfVisibleNodeOrInvisible(Id nodeId) const
|
||||
@@ -245,23 +229,12 @@ bool HierarchyCache::isChildOfVisibleNodeOrInvisible(Id nodeId) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HierarchyCache::isIndexed(Id nodeId) const
|
||||
{
|
||||
HierarchyNode* node = getNode(nodeId);
|
||||
if (!node)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return node->isIndexed();
|
||||
}
|
||||
|
||||
bool HierarchyCache::nodeHasChildren(Id nodeId) const
|
||||
{
|
||||
HierarchyNode* node = getNode(nodeId);
|
||||
if (node)
|
||||
{
|
||||
return node->getChildren().size();
|
||||
return node->getChildrenCount();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -13,20 +13,19 @@ class HierarchyCache
|
||||
public:
|
||||
void clear();
|
||||
|
||||
void createConnection(Id edgeId, Id fromId, Id toId, bool sourceVisible, bool sourceIndexed, bool targetIndexed);
|
||||
void createConnection(Id edgeId, Id fromId, Id toId, bool sourceVisible, bool targetImplicit);
|
||||
|
||||
Id getLastVisibleParentNodeId(Id nodeId) const;
|
||||
size_t getIndexOfLastVisibleParentNode(Id nodeId) const;
|
||||
|
||||
void addAllChildIdsForNodeId(Id nodeId, std::set<Id>* nodeIds, std::set<Id>* edgeIds) const;
|
||||
void addAllVisibleParentsAndChildIdsForNodeId(Id nodeId, std::set<Id>* nodeIds, std::set<Id>* edgeIds) const;
|
||||
void addAllVisibleParentsRecursive(Id nodeId, std::set<Id>* nodeIds, std::set<Id>* edgeIds) const;
|
||||
void addAllVisibleParentIdsForNodeId(Id nodeId, std::set<Id>* nodeIds, std::set<Id>* edgeIds) const;
|
||||
|
||||
void addFirstChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds) const;
|
||||
void addFirstVisibleChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds) const;
|
||||
void addAllChildIdsForNodeId(Id nodeId, std::set<Id>* nodeIds, std::set<Id>* edgeIds) const;
|
||||
void addFirstNonImplicitChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds, std::vector<Id>* edgeIds) const;
|
||||
|
||||
size_t getFirstNonImplicitChildIdsCountForNodeId(Id nodeId) const;
|
||||
|
||||
bool isChildOfVisibleNodeOrInvisible(Id nodeId) const;
|
||||
bool isIndexed(Id nodeId) const;
|
||||
|
||||
bool nodeHasChildren(Id nodeId) const;
|
||||
|
||||
@@ -45,18 +44,18 @@ private:
|
||||
void setParent(HierarchyNode* parent);
|
||||
|
||||
void addChild(HierarchyNode* child);
|
||||
const std::vector<HierarchyNode*>& getChildren() const;
|
||||
|
||||
void addChildIds(std::vector<Id>* nodeIds) const;
|
||||
void addChildIds(std::set<Id>* nodeIds, std::set<Id>* edgeIds) const;
|
||||
size_t getChildrenCount() const;
|
||||
size_t getNonImplicitChildrenCount() const;
|
||||
|
||||
void addNonImplicitChildIds(std::vector<Id>* nodeIds, std::vector<Id>* edgeIds) const;
|
||||
void addChildIdsRecursive(std::set<Id>* nodeIds, std::set<Id>* edgeIds) const;
|
||||
void addVisibleNodeIdsRecursive(std::vector<Id>* nodeIds) const;
|
||||
|
||||
bool isVisible() const;
|
||||
void setIsVisible(bool isVisible);
|
||||
|
||||
bool isIndexed() const;
|
||||
void setIsIndexed(bool isIndexed);
|
||||
bool isImplicit() const;
|
||||
void setIsImplicit(bool isImplicit);
|
||||
|
||||
private:
|
||||
const Id m_nodeId;
|
||||
@@ -66,7 +65,7 @@ private:
|
||||
std::vector<HierarchyNode*> m_children;
|
||||
|
||||
bool m_isVisible;
|
||||
bool m_isIndexed;
|
||||
bool m_isImplicit;
|
||||
};
|
||||
|
||||
HierarchyNode* getNode(Id nodeId) const;
|
||||
|
||||
@@ -991,9 +991,6 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForActiveTokenIds(
|
||||
{
|
||||
TRACE();
|
||||
|
||||
std::shared_ptr<Graph> g = std::make_shared<Graph>();
|
||||
Graph* graph = g.get();
|
||||
|
||||
std::vector<Id> ids(tokenIds);
|
||||
bool isNamespace = false;
|
||||
|
||||
@@ -1014,13 +1011,16 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForActiveTokenIds(
|
||||
if (nodeType & (Node::NODE_NAMESPACE | Node::NODE_PACKAGE))
|
||||
{
|
||||
ids.clear();
|
||||
m_hierarchyCache.addFirstChildIdsForNodeId(elementId, &ids);
|
||||
m_hierarchyCache.addFirstNonImplicitChildIdsForNodeId(elementId, &ids, &edgeIds);
|
||||
edgeIds.clear();
|
||||
|
||||
isNamespace = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeIds.push_back(elementId);
|
||||
m_hierarchyCache.addFirstNonImplicitChildIdsForNodeId(elementId, &nodeIds, &edgeIds);
|
||||
edgeIds.clear();
|
||||
|
||||
std::vector<StorageEdge> edges = m_sqliteIndexStorage.getEdgesBySourceOrTargetId(elementId);
|
||||
for (const StorageEdge& edge : edges)
|
||||
@@ -1086,13 +1086,16 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForActiveTokenIds(
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Graph> g = std::make_shared<Graph>();
|
||||
Graph* graph = g.get();
|
||||
|
||||
if (isNamespace)
|
||||
{
|
||||
addNodesToGraph(nodeIds, graph);
|
||||
}
|
||||
else
|
||||
{
|
||||
addNodesWithChildrenAndEdgesToGraph(nodeIds, edgeIds, graph);
|
||||
addNodesWithParentsAndEdgesToGraph(nodeIds, edgeIds, graph);
|
||||
}
|
||||
|
||||
if (addAggregations)
|
||||
@@ -1110,6 +1113,24 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForActiveTokenIds(
|
||||
return g;
|
||||
}
|
||||
|
||||
std::shared_ptr<Graph> PersistentStorage::getGraphForChildrenOfNodeId(Id nodeId) const
|
||||
{
|
||||
TRACE();
|
||||
|
||||
std::vector<Id> nodeIds;
|
||||
std::vector<Id> edgeIds;
|
||||
|
||||
nodeIds.push_back(nodeId);
|
||||
m_hierarchyCache.addFirstNonImplicitChildIdsForNodeId(nodeId, &nodeIds, &edgeIds);
|
||||
|
||||
std::shared_ptr<Graph> graph = std::make_shared<Graph>();
|
||||
addNodesToGraph(nodeIds, graph.get());
|
||||
addEdgesToGraph(edgeIds, graph.get());
|
||||
|
||||
addComponentAccessToGraph(graph.get());
|
||||
return graph;
|
||||
}
|
||||
|
||||
std::shared_ptr<Graph> PersistentStorage::getGraphForTrail(
|
||||
Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const
|
||||
{
|
||||
@@ -1169,7 +1190,7 @@ std::shared_ptr<Graph> PersistentStorage::getGraphForTrail(
|
||||
|
||||
std::shared_ptr<Graph> graph = std::make_shared<Graph>();
|
||||
|
||||
addNodesWithChildrenAndEdgesToGraph(utility::toVector(nodeIds), utility::toVector(edgeIds), graph.get());
|
||||
addNodesWithParentsAndEdgesToGraph(utility::toVector(nodeIds), utility::toVector(edgeIds), graph.get());
|
||||
addComponentAccessToGraph(graph.get());
|
||||
|
||||
return graph;
|
||||
@@ -1838,6 +1859,8 @@ void PersistentStorage::addNodesToGraph(const std::vector<Id>& nodeIds, Graph* g
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
node->setChildCount(m_hierarchyCache.getFirstNonImplicitChildIdsCountForNodeId(storageNode.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1867,50 +1890,31 @@ void PersistentStorage::addEdgesToGraph(const std::vector<Id>& edgeIds, Graph* g
|
||||
}
|
||||
}
|
||||
|
||||
void PersistentStorage::addNodesWithChildrenAndEdgesToGraph(
|
||||
void PersistentStorage::addNodesWithParentsAndEdgesToGraph(
|
||||
const std::vector<Id>& nodeIds, const std::vector<Id>& edgeIds, Graph* graph
|
||||
) const
|
||||
{
|
||||
TRACE();
|
||||
|
||||
std::vector<Id> nodeIdsFull = nodeIds;
|
||||
std::set<Id> allNodeIds(nodeIds.begin(), nodeIds.end());
|
||||
std::set<Id> allEdgeIds(edgeIds.begin(), edgeIds.end());
|
||||
|
||||
if (edgeIds.size() > 0)
|
||||
{
|
||||
for (const StorageEdge& storageEdge : m_sqliteIndexStorage.getAllByIds<StorageEdge>(edgeIds))
|
||||
{
|
||||
nodeIdsFull.push_back(storageEdge.sourceNodeId);
|
||||
nodeIdsFull.push_back(storageEdge.targetNodeId);
|
||||
allNodeIds.insert(storageEdge.sourceNodeId);
|
||||
allNodeIds.insert(storageEdge.targetNodeId);
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Id> parentNodeIds;
|
||||
std::set<Id> nonIndexedNodeIds;
|
||||
|
||||
for (Id nodeId : nodeIdsFull)
|
||||
for (Id nodeId : allNodeIds)
|
||||
{
|
||||
if (m_hierarchyCache.isIndexed(nodeId))
|
||||
{
|
||||
parentNodeIds.insert(getLastVisibleParentNodeId(nodeId));
|
||||
}
|
||||
else
|
||||
{
|
||||
nonIndexedNodeIds.insert(nodeId);
|
||||
}
|
||||
m_hierarchyCache.addAllVisibleParentIdsForNodeId(nodeId, &parentNodeIds, &allEdgeIds);
|
||||
}
|
||||
|
||||
std::set<Id> allNodeIds;
|
||||
std::set<Id> allEdgeIds(edgeIds.begin(), edgeIds.end());
|
||||
|
||||
for (Id parentNodeId : parentNodeIds)
|
||||
{
|
||||
allNodeIds.insert(parentNodeId);
|
||||
m_hierarchyCache.addAllChildIdsForNodeId(parentNodeId, &allNodeIds, &allEdgeIds);
|
||||
}
|
||||
|
||||
for (Id nonIndexedNodeId : nonIndexedNodeIds)
|
||||
{
|
||||
m_hierarchyCache.addAllVisibleParentsAndChildIdsForNodeId(nonIndexedNodeId, &allNodeIds, &allEdgeIds);
|
||||
}
|
||||
allNodeIds.insert(parentNodeIds.begin(), parentNodeIds.end());
|
||||
|
||||
addNodesToGraph(utility::toVector(allNodeIds), graph);
|
||||
addEdgesToGraph(utility::toVector(allEdgeIds), graph);
|
||||
@@ -1988,7 +1992,7 @@ void PersistentStorage::addAggregationEdgesToGraph(
|
||||
nodeIdsToAdd.push_back(aggregationTargetNodeId);
|
||||
}
|
||||
}
|
||||
addNodesWithChildrenAndEdgesToGraph(nodeIdsToAdd, std::vector<Id>(), graph);
|
||||
addNodesWithParentsAndEdgesToGraph(nodeIdsToAdd, std::vector<Id>(), graph);
|
||||
|
||||
// create aggregation edges between parents and active node
|
||||
Node* sourceNode = graph->getNodeById(nodeId);
|
||||
@@ -2131,23 +2135,21 @@ void PersistentStorage::buildHierarchyCache()
|
||||
return Node::intToType(m_sqliteIndexStorage.getFirstById<StorageNode>(id).type);
|
||||
});
|
||||
|
||||
Cache<Id, bool> indexedNodeCache([this](Id id){
|
||||
Cache<Id, DefinitionKind> definitionKindCache([this](Id id){
|
||||
StorageSymbol symbol = m_sqliteIndexStorage.getFirstById<StorageSymbol>(id);
|
||||
if (symbol.id > 0)
|
||||
{
|
||||
return intToDefinitionKind(symbol.definitionKind) != DEFINITION_NONE;
|
||||
return intToDefinitionKind(symbol.definitionKind);
|
||||
}
|
||||
return false;
|
||||
return DEFINITION_NONE;
|
||||
});
|
||||
|
||||
for (const StorageEdge& edge : memberEdges)
|
||||
{
|
||||
bool isVisible = !(nodeTypeCache.getValue(edge.sourceNodeId) & Node::NODE_NOT_VISIBLE);
|
||||
bool sourceIsIndexed = indexedNodeCache.getValue(edge.sourceNodeId);
|
||||
bool targetIsIndexed = indexedNodeCache.getValue(edge.targetNodeId);
|
||||
bool sourceIsVisible = !(nodeTypeCache.getValue(edge.sourceNodeId) & Node::NODE_NOT_VISIBLE);
|
||||
bool targetIsImplicit = definitionKindCache.getValue(edge.targetNodeId) == DEFINITION_IMPLICIT;
|
||||
|
||||
m_hierarchyCache.createConnection(
|
||||
edge.id, edge.sourceNodeId, edge.targetNodeId, isVisible, sourceIsIndexed, targetIsIndexed);
|
||||
edge.id, edge.sourceNodeId, edge.targetNodeId, sourceIsVisible, targetIsImplicit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ public:
|
||||
|
||||
virtual std::shared_ptr<Graph> getGraphForAll() const;
|
||||
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds, bool* isActiveNamespace = nullptr) const;
|
||||
virtual std::shared_ptr<Graph> getGraphForChildrenOfNodeId(Id nodeId) const;
|
||||
virtual std::shared_ptr<Graph> getGraphForTrail(Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const;
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
|
||||
@@ -159,7 +160,7 @@ private:
|
||||
|
||||
void addNodesToGraph(const std::vector<Id>& nodeIds, Graph* graph) const;
|
||||
void addEdgesToGraph(const std::vector<Id>& edgeIds, Graph* graph) const;
|
||||
void addNodesWithChildrenAndEdgesToGraph(
|
||||
void addNodesWithParentsAndEdgesToGraph(
|
||||
const std::vector<Id>& nodeIds, const std::vector<Id>& edgeIds, Graph* graph) const;
|
||||
|
||||
void addAggregationEdgesToGraph(const Id nodeId, const std::vector<StorageEdge>& edgesToAggregate, Graph* graph) const;
|
||||
|
||||
@@ -49,6 +49,7 @@ public:
|
||||
|
||||
virtual std::shared_ptr<Graph> getGraphForAll() const = 0;
|
||||
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds, bool* isActiveNamespace = nullptr) const = 0;
|
||||
virtual std::shared_ptr<Graph> getGraphForChildrenOfNodeId(Id nodeId) const = 0;
|
||||
virtual std::shared_ptr<Graph> getGraphForTrail(Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const = 0;
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const = 0;
|
||||
|
||||
@@ -165,6 +165,16 @@ std::shared_ptr<Graph> StorageAccessProxy::getGraphForActiveTokenIds(const std::
|
||||
return std::make_shared<Graph>();
|
||||
}
|
||||
|
||||
std::shared_ptr<Graph> StorageAccessProxy::getGraphForChildrenOfNodeId(Id nodeId) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getGraphForChildrenOfNodeId(nodeId);
|
||||
}
|
||||
|
||||
return std::make_shared<Graph>();
|
||||
}
|
||||
|
||||
std::shared_ptr<Graph> StorageAccessProxy::getGraphForTrail(Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const
|
||||
{
|
||||
if (hasSubject())
|
||||
|
||||
@@ -38,6 +38,7 @@ public:
|
||||
|
||||
virtual std::shared_ptr<Graph> getGraphForAll() const;
|
||||
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds, bool* isActiveNamespace = nullptr) const;
|
||||
virtual std::shared_ptr<Graph> getGraphForChildrenOfNodeId(Id nodeId) const;
|
||||
virtual std::shared_ptr<Graph> getGraphForTrail(Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const;
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
|
||||
|
||||
@@ -140,7 +140,7 @@ void Graph::removeNode(Node* node)
|
||||
}
|
||||
);
|
||||
|
||||
if (node->getEdges().size())
|
||||
if (node->getEdgeCount())
|
||||
{
|
||||
LOG_ERROR("Node still has edges.");
|
||||
}
|
||||
|
||||
+56
-20
@@ -125,6 +125,18 @@ Node::Node(Id id, NodeType type, NameHierarchy nameHierarchy, bool defined)
|
||||
, m_defined(defined)
|
||||
, m_implicit(false)
|
||||
, m_explicit(false)
|
||||
, m_childCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
Node::Node(const Node& other)
|
||||
: Token(other)
|
||||
, m_type(other.m_type)
|
||||
, m_nameHierarchy(other.m_nameHierarchy)
|
||||
, m_defined(other.m_defined)
|
||||
, m_implicit(other.m_implicit)
|
||||
, m_explicit(other.m_explicit)
|
||||
, m_childCount(other.m_childCount)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -199,19 +211,33 @@ void Node::setExplicit(bool bExplicit)
|
||||
m_explicit = bExplicit;
|
||||
}
|
||||
|
||||
const std::vector<Edge*>& Node::getEdges() const
|
||||
size_t Node::getChildCount() const
|
||||
{
|
||||
return m_edges;
|
||||
return m_childCount;
|
||||
}
|
||||
|
||||
void Node::setChildCount(size_t childCount)
|
||||
{
|
||||
m_childCount = childCount;
|
||||
}
|
||||
|
||||
size_t Node::getEdgeCount() const
|
||||
{
|
||||
return m_edges.size();
|
||||
}
|
||||
|
||||
void Node::addEdge(Edge* edge)
|
||||
{
|
||||
m_edges.push_back(edge);
|
||||
m_edges.emplace(edge->getId(), edge);
|
||||
}
|
||||
|
||||
void Node::removeEdge(Edge* edge)
|
||||
{
|
||||
m_edges.erase(find(m_edges.begin(), m_edges.end(), edge));
|
||||
auto it = m_edges.find(edge->getId());
|
||||
if (it != m_edges.end())
|
||||
{
|
||||
m_edges.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
Node* Node::getParentNode() const
|
||||
@@ -246,11 +272,16 @@ Edge* Node::getMemberEdge() const
|
||||
|
||||
Edge* Node::findEdge(std::function<bool(Edge*)> func) const
|
||||
{
|
||||
std::vector<Edge*>::const_iterator it = find_if(m_edges.begin(), m_edges.end(), func);
|
||||
auto it = find_if(m_edges.begin(), m_edges.end(),
|
||||
[func](std::pair<Id, Edge*> p)
|
||||
{
|
||||
return func(p.second);
|
||||
}
|
||||
);
|
||||
|
||||
if (it != m_edges.end())
|
||||
{
|
||||
return *it;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -263,12 +294,12 @@ Edge* Node::findEdgeOfType(Edge::EdgeTypeMask mask) const
|
||||
|
||||
Edge* Node::findEdgeOfType(Edge::EdgeTypeMask mask, std::function<bool(Edge*)> func) const
|
||||
{
|
||||
std::vector<Edge*>::const_iterator it = find_if(m_edges.begin(), m_edges.end(),
|
||||
[mask, func](Edge* e)
|
||||
auto it = find_if(m_edges.begin(), m_edges.end(),
|
||||
[mask, func](std::pair<Id, Edge*> p)
|
||||
{
|
||||
if (e->isType(mask))
|
||||
if (p.second->isType(mask))
|
||||
{
|
||||
return func(e);
|
||||
return func(p.second);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -276,7 +307,7 @@ Edge* Node::findEdgeOfType(Edge::EdgeTypeMask mask, std::function<bool(Edge*)> f
|
||||
|
||||
if (it != m_edges.end())
|
||||
{
|
||||
return *it;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -284,12 +315,12 @@ Edge* Node::findEdgeOfType(Edge::EdgeTypeMask mask, std::function<bool(Edge*)> f
|
||||
|
||||
Node* Node::findChildNode(std::function<bool(Node*)> func) const
|
||||
{
|
||||
std::vector<Edge*>::const_iterator it = find_if(m_edges.begin(), m_edges.end(),
|
||||
[&func](Edge* e)
|
||||
auto it = find_if(m_edges.begin(), m_edges.end(),
|
||||
[&func](std::pair<Id, Edge*> p)
|
||||
{
|
||||
if (e->getType() == Edge::EDGE_MEMBER)
|
||||
if (p.second->getType() == Edge::EDGE_MEMBER)
|
||||
{
|
||||
return func(e->getTo());
|
||||
return func(p.second->getTo());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -297,7 +328,7 @@ Node* Node::findChildNode(std::function<bool(Node*)> func) const
|
||||
|
||||
if (it != m_edges.end())
|
||||
{
|
||||
return (*it)->getTo();
|
||||
return it->second->getTo();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -305,17 +336,22 @@ Node* Node::findChildNode(std::function<bool(Node*)> func) const
|
||||
|
||||
void Node::forEachEdge(std::function<void(Edge*)> func) const
|
||||
{
|
||||
for_each(m_edges.begin(), m_edges.end(), func);
|
||||
for_each(m_edges.begin(), m_edges.end(),
|
||||
[func](std::pair<Id, Edge*> p)
|
||||
{
|
||||
func(p.second);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void Node::forEachEdgeOfType(Edge::EdgeTypeMask mask, std::function<void(Edge*)> func) const
|
||||
{
|
||||
for_each(m_edges.begin(), m_edges.end(),
|
||||
[mask, func](Edge* e)
|
||||
[mask, func](std::pair<Id, Edge*> p)
|
||||
{
|
||||
if (e->isType(mask))
|
||||
if (p.second->isType(mask))
|
||||
{
|
||||
func(e);
|
||||
func(p.second);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "data/graph/Edge.h"
|
||||
#include "data/graph/Token.h"
|
||||
@@ -58,6 +58,7 @@ public:
|
||||
static const NodeTypeMask NODE_USEABLE_TYPE;
|
||||
|
||||
Node(Id id, NodeType type, NameHierarchy nameHierarchy, bool defined);
|
||||
Node(const Node& other);
|
||||
virtual ~Node();
|
||||
|
||||
NodeType getType() const;
|
||||
@@ -77,7 +78,10 @@ public:
|
||||
bool isExplicit() const;
|
||||
void setExplicit(bool bExplicit);
|
||||
|
||||
const std::vector<Edge*>& getEdges() const;
|
||||
size_t getChildCount() const;
|
||||
void setChildCount(size_t childCount);
|
||||
|
||||
size_t getEdgeCount() const;
|
||||
|
||||
void addEdge(Edge* edge);
|
||||
void removeEdge(Edge* edge);
|
||||
@@ -115,13 +119,15 @@ public:
|
||||
private:
|
||||
void operator=(const Node&);
|
||||
|
||||
std::vector<Edge*> m_edges;
|
||||
std::map<Id, Edge*> m_edges;
|
||||
|
||||
NodeType m_type;
|
||||
NameHierarchy m_nameHierarchy;
|
||||
bool m_defined;
|
||||
bool m_implicit;
|
||||
bool m_explicit;
|
||||
|
||||
size_t m_childCount;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& ostream, const Node& node);
|
||||
|
||||
Reference in New Issue
Block a user