diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index a4c4758a..addc7752 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -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 edge = m_dummyEdges[i]; + std::shared_ptr 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 aggregationIds = - utility::toVector(edge->data->getComponent()->getAggregationIds()); + m_graph->addEdgeAsPlainCopy(edge); + } + ); - if (m_graph->getEdgeById(aggregationIds[0]) != nullptr) + Node* node = m_graph->getNodeById(nodeId); + std::vector> newDummyNodes = createDummyNodeTopDown(node, node->getLastParentNode()->getId()); + if (newDummyNodes.size() != 1) + { + LOG_ERROR("Wrong amount of dummy nodes created"); + return; + } + std::shared_ptr 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 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 aggregationIds = + utility::toVector(edge->data->getComponent()->getAggregationIds()); - std::shared_ptr 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( - e->getFrom()->getId(), e->getTo()->getId(), m_graph->addEdgeAsPlainCopy(e))); - } + break; } - ); + + std::shared_ptr aggregationGraph = m_storageAccess->getGraphForActiveTokenIds(aggregationIds); + + aggregationGraph->forEachEdge( + [this](Edge* e) + { + if (!e->isType(Edge::EDGE_MEMBER)) + { + m_dummyEdges.push_back(std::make_shared( + 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 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 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); } diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index 6d637233..b28d7097 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -85,7 +85,6 @@ private: void setVisibility(bool noActive); void setActiveAndVisibility(const std::vector& activeTokenIds); void setNodeActiveRecursive(DummyNode* node, const std::vector& activeTokenIds, bool* noActive) const; - void removeImplicitChildrenRecursive(DummyNode* node); bool setNodeVisibilityRecursiveBottomUp(DummyNode* node, bool noActive) const; void setNodeVisibilityRecursiveTopDown(DummyNode* node, bool parentExpanded) const; diff --git a/src/lib/component/controller/helper/DummyNode.h b/src/lib/component/controller/helper/DummyNode.h index d003016a..a131e4a7 100644 --- a/src/lib/component/controller/helper/DummyNode.h +++ b/src/lib/component/controller/helper/DummyNode.h @@ -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 subNode : subNodes) + { + if (subNode->isAccessNode()) + { + for (std::shared_ptr subSubNode : subNode->subNodes) + { + if (subSubNode->isGraphNode() && !subSubNode->data->isImplicit()) + { + subNodeCount++; + } + } + } + } + + return subNodeCount < childCount; + } + + std::map> getSubGraphNodes() const + { + std::map> subGraphNodes; + + for (std::shared_ptr subNode : subNodes) + { + if (subNode->isAccessNode()) + { + for (std::shared_ptr subSubNode : subNode->subNodes) + { + if (subSubNode->isGraphNode()) + { + subGraphNodes.emplace(subSubNode->tokenId, subSubNode); + } + } + } + } + + return subGraphNodes; + } + + void replaceSubGraphNodes(std::map> subGraphNodes) const + { + for (std::shared_ptr subNode : subNodes) + { + if (subNode->isAccessNode()) + { + for (size_t i = 0; i < subNode->subNodes.size(); i++) + { + std::shared_ptr 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> getAccessNodes() const + { + std::vector> accessNodes; + for (std::shared_ptr subNode : subNodes) + { + if (subNode->isAccessNode()) + { + accessNodes.push_back(subNode); + } + } + return accessNodes; + } + + void replaceAccessNodes(const std::vector>& 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; diff --git a/src/lib/data/HierarchyCache.cpp b/src/lib/data/HierarchyCache.cpp index 7ba2aacc..b52f39e3 100644 --- a/src/lib/data/HierarchyCache.cpp +++ b/src/lib/data/HierarchyCache.cpp @@ -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::getChildren() const +size_t HierarchyCache::HierarchyNode::getChildrenCount() const { - return m_children; + return m_children.size(); } -void HierarchyCache::HierarchyNode::addChildIds(std::vector* 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* nodeIds, std::set* edgeIds) const +void HierarchyCache::HierarchyNode::addNonImplicitChildIds(std::vector* nodeIds, std::vector* 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* nodeIds, } } -void HierarchyCache::HierarchyNode::addVisibleNodeIdsRecursive(std::vector* 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* nodeIds, std::set* edgeIds) const +void HierarchyCache::addAllVisibleParentIdsForNodeId(Id nodeId, std::set* nodeIds, std::set* edgeIds) const { HierarchyNode* node = getNode(nodeId); - if (node && node->isVisible()) - { - node->addChildIdsRecursive(nodeIds, edgeIds); - } -} - -void HierarchyCache::addAllVisibleParentsAndChildIdsForNodeId(Id nodeId, std::set* nodeIds, std::set* 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* nodeIds) const +void HierarchyCache::addAllChildIdsForNodeId(Id nodeId, std::set* nodeIds, std::set* 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* nodeIds) const +void HierarchyCache::addFirstNonImplicitChildIdsForNodeId(Id nodeId, std::vector* nodeIds, std::vector* 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; diff --git a/src/lib/data/HierarchyCache.h b/src/lib/data/HierarchyCache.h index 60da8d6c..25fdcaf2 100644 --- a/src/lib/data/HierarchyCache.h +++ b/src/lib/data/HierarchyCache.h @@ -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* nodeIds, std::set* edgeIds) const; - void addAllVisibleParentsAndChildIdsForNodeId(Id nodeId, std::set* nodeIds, std::set* edgeIds) const; - void addAllVisibleParentsRecursive(Id nodeId, std::set* nodeIds, std::set* edgeIds) const; + void addAllVisibleParentIdsForNodeId(Id nodeId, std::set* nodeIds, std::set* edgeIds) const; - void addFirstChildIdsForNodeId(Id nodeId, std::vector* nodeIds) const; - void addFirstVisibleChildIdsForNodeId(Id nodeId, std::vector* nodeIds) const; + void addAllChildIdsForNodeId(Id nodeId, std::set* nodeIds, std::set* edgeIds) const; + void addFirstNonImplicitChildIdsForNodeId(Id nodeId, std::vector* nodeIds, std::vector* 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& getChildren() const; - void addChildIds(std::vector* nodeIds) const; - void addChildIds(std::set* nodeIds, std::set* edgeIds) const; + size_t getChildrenCount() const; + size_t getNonImplicitChildrenCount() const; + + void addNonImplicitChildIds(std::vector* nodeIds, std::vector* edgeIds) const; void addChildIdsRecursive(std::set* nodeIds, std::set* edgeIds) const; - void addVisibleNodeIdsRecursive(std::vector* 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 m_children; bool m_isVisible; - bool m_isIndexed; + bool m_isImplicit; }; HierarchyNode* getNode(Id nodeId) const; diff --git a/src/lib/data/PersistentStorage.cpp b/src/lib/data/PersistentStorage.cpp index d5d74ca3..028d930b 100644 --- a/src/lib/data/PersistentStorage.cpp +++ b/src/lib/data/PersistentStorage.cpp @@ -991,9 +991,6 @@ std::shared_ptr PersistentStorage::getGraphForActiveTokenIds( { TRACE(); - std::shared_ptr g = std::make_shared(); - Graph* graph = g.get(); - std::vector ids(tokenIds); bool isNamespace = false; @@ -1014,13 +1011,16 @@ std::shared_ptr 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 edges = m_sqliteIndexStorage.getEdgesBySourceOrTargetId(elementId); for (const StorageEdge& edge : edges) @@ -1086,13 +1086,16 @@ std::shared_ptr PersistentStorage::getGraphForActiveTokenIds( } } + std::shared_ptr g = std::make_shared(); + 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 PersistentStorage::getGraphForActiveTokenIds( return g; } +std::shared_ptr PersistentStorage::getGraphForChildrenOfNodeId(Id nodeId) const +{ + TRACE(); + + std::vector nodeIds; + std::vector edgeIds; + + nodeIds.push_back(nodeId); + m_hierarchyCache.addFirstNonImplicitChildIdsForNodeId(nodeId, &nodeIds, &edgeIds); + + std::shared_ptr graph = std::make_shared(); + addNodesToGraph(nodeIds, graph.get()); + addEdgesToGraph(edgeIds, graph.get()); + + addComponentAccessToGraph(graph.get()); + return graph; +} + std::shared_ptr PersistentStorage::getGraphForTrail( Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const { @@ -1169,7 +1190,7 @@ std::shared_ptr PersistentStorage::getGraphForTrail( std::shared_ptr graph = std::make_shared(); - 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& nodeIds, Graph* g ); } } + + node->setChildCount(m_hierarchyCache.getFirstNonImplicitChildIdsCountForNodeId(storageNode.id)); } } } @@ -1867,50 +1890,31 @@ void PersistentStorage::addEdgesToGraph(const std::vector& edgeIds, Graph* g } } -void PersistentStorage::addNodesWithChildrenAndEdgesToGraph( +void PersistentStorage::addNodesWithParentsAndEdgesToGraph( const std::vector& nodeIds, const std::vector& edgeIds, Graph* graph ) const { TRACE(); - std::vector nodeIdsFull = nodeIds; + std::set allNodeIds(nodeIds.begin(), nodeIds.end()); + std::set allEdgeIds(edgeIds.begin(), edgeIds.end()); + if (edgeIds.size() > 0) { for (const StorageEdge& storageEdge : m_sqliteIndexStorage.getAllByIds(edgeIds)) { - nodeIdsFull.push_back(storageEdge.sourceNodeId); - nodeIdsFull.push_back(storageEdge.targetNodeId); + allNodeIds.insert(storageEdge.sourceNodeId); + allNodeIds.insert(storageEdge.targetNodeId); } } std::set parentNodeIds; - std::set 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 allNodeIds; - std::set 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(), graph); + addNodesWithParentsAndEdgesToGraph(nodeIdsToAdd, std::vector(), 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(id).type); }); - Cache indexedNodeCache([this](Id id){ + Cache definitionKindCache([this](Id id){ StorageSymbol symbol = m_sqliteIndexStorage.getFirstById(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); } } - diff --git a/src/lib/data/PersistentStorage.h b/src/lib/data/PersistentStorage.h index 0e34f7db..0c6b6ec0 100644 --- a/src/lib/data/PersistentStorage.h +++ b/src/lib/data/PersistentStorage.h @@ -108,6 +108,7 @@ public: virtual std::shared_ptr getGraphForAll() const; virtual std::shared_ptr getGraphForActiveTokenIds(const std::vector& tokenIds, bool* isActiveNamespace = nullptr) const; + virtual std::shared_ptr getGraphForChildrenOfNodeId(Id nodeId) const; virtual std::shared_ptr getGraphForTrail(Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const; virtual std::vector getActiveTokenIdsForId(Id tokenId, Id* declarationId) const; @@ -159,7 +160,7 @@ private: void addNodesToGraph(const std::vector& nodeIds, Graph* graph) const; void addEdgesToGraph(const std::vector& edgeIds, Graph* graph) const; - void addNodesWithChildrenAndEdgesToGraph( + void addNodesWithParentsAndEdgesToGraph( const std::vector& nodeIds, const std::vector& edgeIds, Graph* graph) const; void addAggregationEdgesToGraph(const Id nodeId, const std::vector& edgesToAggregate, Graph* graph) const; diff --git a/src/lib/data/access/StorageAccess.h b/src/lib/data/access/StorageAccess.h index 3af197b5..c9c6e2ed 100644 --- a/src/lib/data/access/StorageAccess.h +++ b/src/lib/data/access/StorageAccess.h @@ -49,6 +49,7 @@ public: virtual std::shared_ptr getGraphForAll() const = 0; virtual std::shared_ptr getGraphForActiveTokenIds(const std::vector& tokenIds, bool* isActiveNamespace = nullptr) const = 0; + virtual std::shared_ptr getGraphForChildrenOfNodeId(Id nodeId) const = 0; virtual std::shared_ptr getGraphForTrail(Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const = 0; virtual std::vector getActiveTokenIdsForId(Id tokenId, Id* declarationId) const = 0; diff --git a/src/lib/data/access/StorageAccessProxy.cpp b/src/lib/data/access/StorageAccessProxy.cpp index 6f78f064..2cd82f7f 100644 --- a/src/lib/data/access/StorageAccessProxy.cpp +++ b/src/lib/data/access/StorageAccessProxy.cpp @@ -165,6 +165,16 @@ std::shared_ptr StorageAccessProxy::getGraphForActiveTokenIds(const std:: return std::make_shared(); } +std::shared_ptr StorageAccessProxy::getGraphForChildrenOfNodeId(Id nodeId) const +{ + if (hasSubject()) + { + return m_subject->getGraphForChildrenOfNodeId(nodeId); + } + + return std::make_shared(); +} + std::shared_ptr StorageAccessProxy::getGraphForTrail(Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const { if (hasSubject()) diff --git a/src/lib/data/access/StorageAccessProxy.h b/src/lib/data/access/StorageAccessProxy.h index a95ec740..05dadb00 100644 --- a/src/lib/data/access/StorageAccessProxy.h +++ b/src/lib/data/access/StorageAccessProxy.h @@ -38,6 +38,7 @@ public: virtual std::shared_ptr getGraphForAll() const; virtual std::shared_ptr getGraphForActiveTokenIds(const std::vector& tokenIds, bool* isActiveNamespace = nullptr) const; + virtual std::shared_ptr getGraphForChildrenOfNodeId(Id nodeId) const; virtual std::shared_ptr getGraphForTrail(Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const; virtual std::vector getActiveTokenIdsForId(Id tokenId, Id* declarationId) const; diff --git a/src/lib/data/graph/Graph.cpp b/src/lib/data/graph/Graph.cpp index 11d7439c..36767ceb 100644 --- a/src/lib/data/graph/Graph.cpp +++ b/src/lib/data/graph/Graph.cpp @@ -140,7 +140,7 @@ void Graph::removeNode(Node* node) } ); - if (node->getEdges().size()) + if (node->getEdgeCount()) { LOG_ERROR("Node still has edges."); } diff --git a/src/lib/data/graph/Node.cpp b/src/lib/data/graph/Node.cpp index b3ed60e6..26a604b0 100644 --- a/src/lib/data/graph/Node.cpp +++ b/src/lib/data/graph/Node.cpp @@ -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& 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 func) const { - std::vector::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 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 func) const { - std::vector::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 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 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 f Node* Node::findChildNode(std::function func) const { - std::vector::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 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 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 func) const void Node::forEachEdge(std::function func) const { - for_each(m_edges.begin(), m_edges.end(), func); + for_each(m_edges.begin(), m_edges.end(), + [func](std::pair p) + { + func(p.second); + } + ); } void Node::forEachEdgeOfType(Edge::EdgeTypeMask mask, std::function func) const { for_each(m_edges.begin(), m_edges.end(), - [mask, func](Edge* e) + [mask, func](std::pair p) { - if (e->isType(mask)) + if (p.second->isType(mask)) { - func(e); + func(p.second); } } ); diff --git a/src/lib/data/graph/Node.h b/src/lib/data/graph/Node.h index c1f369b7..724a9319 100644 --- a/src/lib/data/graph/Node.h +++ b/src/lib/data/graph/Node.h @@ -3,8 +3,8 @@ #include #include +#include #include -#include #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& 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 m_edges; + std::map 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);