diff --git a/src/lib/data/search/SearchIndex.cpp b/src/lib/data/search/SearchIndex.cpp index 76e87bf0..5cd499e6 100644 --- a/src/lib/data/search/SearchIndex.cpp +++ b/src/lib/data/search/SearchIndex.cpp @@ -16,9 +16,9 @@ SearchIndex::~SearchIndex() { } -void SearchIndex::addNode(Id id, const std::string& name) +void SearchIndex::addNode(Id id, const std::string& name, Node::NodeTypeMask type) { - Node* currentNode = m_root; + SearchNode* currentNode = m_root; std::string remaining = name; while (remaining.size() > 0) @@ -26,7 +26,7 @@ void SearchIndex::addNode(Id id, const std::string& name) auto it = currentNode->edges.find(remaining[0]); if (it != currentNode->edges.end()) { - Edge* currentEdge = it->second; + SearchEdge* currentEdge = it->second; const std::string& edgeString = currentEdge->s; size_t matchCount = 1; @@ -42,9 +42,9 @@ void SearchIndex::addNode(Id id, const std::string& name) if (matchCount < edgeString.size()) { // split current edge - std::shared_ptr n = std::make_shared(); + std::shared_ptr n = std::make_shared(); m_nodes.push_back(n); - std::shared_ptr e = std::make_shared(); + std::shared_ptr e = std::make_shared(); m_edges.push_back(e); e->s = edgeString.substr(matchCount); @@ -61,9 +61,9 @@ void SearchIndex::addNode(Id id, const std::string& name) } else { - std::shared_ptr n = std::make_shared(); + std::shared_ptr n = std::make_shared(); m_nodes.push_back(n); - std::shared_ptr e = std::make_shared(); + std::shared_ptr e = std::make_shared(); m_edges.push_back(e); e->s = remaining; @@ -77,6 +77,7 @@ void SearchIndex::addNode(Id id, const std::string& name) } currentNode->elementIds.insert(id); + currentNode->mask |= type; } void SearchIndex::finishSetup() @@ -92,24 +93,24 @@ void SearchIndex::clear() m_nodes.clear(); m_edges.clear(); - std::shared_ptr n = std::make_shared(); + std::shared_ptr n = std::make_shared(); m_nodes.push_back(n); m_root = n.get(); } std::vector SearchIndex::search( - const std::string& query, size_t maxResultCount, size_t maxBestScoredLength) const + const std::string& query, Node::NodeTypeMask filter, size_t maxResultCount, size_t maxBestScoredLength) const { // find paths containing query - Path startPath; + SearchPath startPath; startPath.node = m_root; - std::vector paths; - searchRecursive(startPath, utility::toLowerCase(query), &paths); + std::vector paths; + searchRecursive(startPath, utility::toLowerCase(query), filter, &paths); // create scored search results - std::multiset searchResults = createScoredResults(paths, maxResultCount * 3); + std::multiset searchResults = createScoredResults(paths, filter, maxResultCount * 3); // find best scores std::map scoresCache; @@ -130,12 +131,12 @@ std::vector SearchIndex::search( return std::vector(bestResults.begin(), it); } -void SearchIndex::populateEdgeGate(Edge* e) +void SearchIndex::populateEdgeGate(SearchEdge* e) { - Node* target = e->target; + SearchNode* target = e->target; for (auto p : target->edges) { - Edge* targetEdge = p.second; + SearchEdge* targetEdge = p.second; populateEdgeGate(targetEdge); utility::append(e->gate, targetEdge->gate); } @@ -146,9 +147,9 @@ void SearchIndex::populateEdgeGate(Edge* e) } void SearchIndex::searchRecursive( - const Path& path, const std::string& remainingQuery, std::vector* results) const + const SearchPath& path, const std::string& remainingQuery, Node::NodeTypeMask filter, std::vector* results) const { - if (remainingQuery.size() == 0) + if (remainingQuery.size() == 0 && (!filter || (path.node->mask & filter))) { results->push_back(path); return; @@ -156,7 +157,7 @@ void SearchIndex::searchRecursive( for (auto p : path.node->edges) { - const Edge* currentEdge = p.second; + const SearchEdge* currentEdge = p.second; // test if s passes the edge's gate. bool passesGate = true; @@ -185,45 +186,46 @@ void SearchIndex::searchRecursive( } } - Path currentPath; + SearchPath currentPath; currentPath.node = currentEdge->target; currentPath.indices = indices; currentPath.text = path.text + edgeString; - searchRecursive(currentPath, remainingQuery.substr(j), results); + searchRecursive(currentPath, remainingQuery.substr(j), filter, results); } } } -std::multiset SearchIndex::createScoredResults(const std::vector& paths, size_t maxResultCount) const +std::multiset SearchIndex::createScoredResults( + const std::vector& paths, Node::NodeTypeMask filter, size_t maxResultCount) const { // score and order initial paths - std::multiset, bool(*)(const std::pair&, const std::pair&)> scoredPaths( - [](const std::pair& a, const std::pair& b) + std::multiset, bool(*)(const std::pair&, const std::pair&)> scoredPaths( + [](const std::pair& a, const std::pair& b) { return a.first > b.first; } ); - for (const Path& path : paths) + for (const SearchPath& path : paths) { scoredPaths.insert(std::make_pair(scoreText(path.text, path.indices), path)); } // score paths and subpaths std::multiset searchResults; - for (const std::pair& p : scoredPaths) + for (const std::pair& p : scoredPaths) { - std::vector currentPaths; + std::vector currentPaths; currentPaths.push_back(p.second); while (currentPaths.size()) { - std::vector nextPaths; + std::vector nextPaths; - for (const Path& path : currentPaths) + for (const SearchPath& path : currentPaths) { - if (path.node->elementIds.size()) + if (path.node->elementIds.size() && (!filter || (path.node->mask & filter))) { SearchResult result; result.text = path.text; @@ -240,8 +242,8 @@ std::multiset SearchIndex::createScoredResults(const std::vector

edges) { - const Edge* edge = p.second; - Path nextPath; + const SearchEdge* edge = p.second; + SearchPath nextPath; nextPath.indices = path.indices; nextPath.node = edge->target; nextPath.text = path.text + edge->s; diff --git a/src/lib/data/search/SearchIndex.h b/src/lib/data/search/SearchIndex.h index cfc7fdfb..f678a5a6 100644 --- a/src/lib/data/search/SearchIndex.h +++ b/src/lib/data/search/SearchIndex.h @@ -9,6 +9,7 @@ #include #include "utility/types.h" +#include "data/graph/Node.h" struct SearchResult { @@ -29,41 +30,43 @@ public: SearchIndex(); virtual ~SearchIndex(); - void addNode(Id id, const std::string& name); + void addNode(Id id, const std::string& name, Node::NodeTypeMask type = 0); void finishSetup(); void clear(); // maxResultCount == 0 means "no restriction". - std::vector search(const std::string& query, size_t maxResultCount, size_t maxBestScoredLength = 0) const; + std::vector search(const std::string& query, Node::NodeTypeMask filter, size_t maxResultCount, size_t maxBestScoredLength = 0) const; private: - struct Node; - struct Edge; + struct SearchEdge; - struct Node + struct SearchNode { std::set elementIds; - std::map edges; + Node::NodeTypeMask mask = 0; + std::map edges; }; - struct Edge + struct SearchEdge { - Node* target; + SearchNode* target; std::string s; std::unordered_set gate; }; - struct Path + struct SearchPath { std::string text; std::vector indices; - Node* node; + SearchNode* node; }; - void populateEdgeGate(Edge* e); - void searchRecursive(const Path& path, const std::string& remainingQuery, std::vector* results) const; + void populateEdgeGate(SearchEdge* e); + void searchRecursive(const SearchPath& path, const std::string& remainingQuery, Node::NodeTypeMask filter, + std::vector* results) const; - std::multiset createScoredResults(const std::vector& paths, size_t maxResultCount) const; + std::multiset createScoredResults( + const std::vector& paths, Node::NodeTypeMask filter, size_t maxResultCount) const; static SearchResult bestScoredResult( SearchResult result, std::map* scoresCache, size_t maxBestScoredLength); @@ -81,9 +84,9 @@ public: size_t maxBestScoredLength); private: - std::vector> m_nodes; - std::vector> m_edges; - Node* m_root; + std::vector> m_nodes; + std::vector> m_edges; + SearchNode* m_root; }; #endif // SEARCH_INDEX_H diff --git a/src/lib/data/storage/PersistentStorage.cpp b/src/lib/data/storage/PersistentStorage.cpp index 9712c081..8c661ddc 100644 --- a/src/lib/data/storage/PersistentStorage.cpp +++ b/src/lib/data/storage/PersistentStorage.cpp @@ -627,7 +627,7 @@ std::vector PersistentStorage::getAutocompletionSymbolMatches( const std::string& query, Node::NodeTypeMask filter, size_t maxResultsCount) const { // search in indices - std::vector results = m_symbolIndex.search(query, maxResultsCount, maxResultsCount); + std::vector results = m_symbolIndex.search(query, filter, maxResultsCount, maxResultsCount); // fetch StorageNodes for node ids std::map storageNodeMap; @@ -676,11 +676,6 @@ std::vector PersistentStorage::getAutocompletionSymbolMatches( } } - if (filter && !(filter & Node::intToType(firstNode->type))) - { - continue; - } - match.name = result.text; match.text = result.text; @@ -714,7 +709,7 @@ std::vector PersistentStorage::getAutocompletionSymbolMatches( std::vector PersistentStorage::getAutocompletionFileMatches(const std::string& query, size_t maxResultsCount) const { - std::vector results = m_fileIndex.search(query, maxResultsCount); + std::vector results = m_fileIndex.search(query, Node::NODE_FILE, maxResultsCount); // create SearchMatches std::vector matches; @@ -749,7 +744,7 @@ std::vector PersistentStorage::getAutocompletionCommandMatches( const std::string& query, Node::NodeTypeMask filter) const { // search in indices - std::vector results = m_commandIndex.search(query, 0); + std::vector results = m_commandIndex.search(query, 0, 0); // create SearchMatches std::vector matches; @@ -2467,7 +2462,8 @@ void PersistentStorage::buildSearchIndex() for (StorageNode& node : m_sqliteIndexStorage.getAll()) { - if (Node::intToType(node.type) == Node::NODE_FILE) + Node::NodeType type = Node::intToType(node.type); + if (type == Node::NODE_FILE) { auto it = m_fileNodePaths.find(node.id); if (it != m_fileNodePaths.end()) @@ -2479,7 +2475,7 @@ void PersistentStorage::buildSearchIndex() filePath = filePath.relativeTo(dbPath); } - m_fileIndex.addNode(node.id, filePath.str()); + m_fileIndex.addNode(node.id, filePath.str(), type); } } else @@ -2499,7 +2495,7 @@ void PersistentStorage::buildSearchIndex() name = utility::replaceBetween(name, '<', '>', ".."); } - m_symbolIndex.addNode(node.id, name); + m_symbolIndex.addNode(node.id, name, type); } } } diff --git a/src/test/SearchIndexTestSuite.h b/src/test/SearchIndexTestSuite.h index a4edd025..fe1d048c 100644 --- a/src/test/SearchIndexTestSuite.h +++ b/src/test/SearchIndexTestSuite.h @@ -12,7 +12,7 @@ public: SearchIndex index; index.addNode(1, NameHierarchy::deserialize("::\tmfoo\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("oo", 0); + std::vector results = index.search("oo", 0, 0); TS_ASSERT_EQUALS(1, results.size()); TS_ASSERT_EQUALS(1, results[0].elementIds.size()); @@ -24,7 +24,7 @@ public: SearchIndex index; index.addNode(1, NameHierarchy::deserialize("::\tmfoo\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("oo", 0); + std::vector results = index.search("oo", 0, 0); TS_ASSERT_EQUALS(1, results.size()); TS_ASSERT_EQUALS(2, results[0].indices.size()); @@ -38,7 +38,7 @@ public: index.addNode(1, NameHierarchy::deserialize("::\tmfor\tsvoid\tp() const").getQualifiedName()); index.addNode(2, NameHierarchy::deserialize("::\tmfos\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("fo", 0); + std::vector results = index.search("fo", 0, 0); TS_ASSERT_EQUALS(2, results.size()); TS_ASSERT_EQUALS(1, results[0].elementIds.size()); @@ -53,7 +53,7 @@ public: index.addNode(1, NameHierarchy::deserialize("::\tmfoo\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); index.clear(); - std::vector results = index.search("oo", 0); + std::vector results = index.search("oo", 0, 0); TS_ASSERT_EQUALS(0, results.size()); } @@ -64,7 +64,7 @@ public: index.addNode(1, NameHierarchy::deserialize("::\tmfoo1\tsvoid\tp() const").getQualifiedName()); index.addNode(2, NameHierarchy::deserialize("::\tmfoo2\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("oo", 1); + std::vector results = index.search("oo", 0, 1); TS_ASSERT_EQUALS(1, results.size()); } @@ -75,7 +75,7 @@ public: index.addNode(1, NameHierarchy::deserialize("::\tmfoo1\tsvoid\tp() const").getQualifiedName()); index.addNode(2, NameHierarchy::deserialize("::\tmFOO2\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("oo", 0); + std::vector results = index.search("oo", 0, 0); TS_ASSERT_EQUALS(2, results.size()); } @@ -87,7 +87,7 @@ public: index.addNode(1, NameHierarchy::deserialize("::\tmoaabbcc\tsvoid\tp() const").getQualifiedName()); index.addNode(2, NameHierarchy::deserialize("::\tmocbcabc\tsvoid\tp() const").getQualifiedName()); index.finishSetup(); - std::vector results = index.search("abc", 0); + std::vector results = index.search("abc", 0, 0); TS_ASSERT_EQUALS(2, results.size()); TS_ASSERT_EQUALS("ocbcabc", results[0].text);