logic: search ui performance optimization

* replaced the implementation of the search index. the search index now uses a search-trie. edges have gates that can be used to check if a character can be matched when following the edge.
* SearchMatches now have a text and a list of NameHierarchies that share this node (instead of Ids, so that nodes must be found by names (which makes sure that SearchMatches are still valid after refresh).
* when parsing a project's description the CodeController now looks for NameHierarchies instead of SearchNode names to find ids of linked elements.
This commit is contained in:
malte_langkabel
2016-04-04 15:39:39 +02:00
parent ffc00829f0
commit f3dc12b0ed
21 changed files with 410 additions and 1367 deletions
@@ -14,7 +14,7 @@
LET'S GET STARTED!\n
\tTo keep things simple just click the "main" symbol below to start the tour.\n
\n
[main](); // <- start here\n\n
[main\tint\r()](); // <- start here\n\n
</description>
</info>
<source>
-168
View File
@@ -1,171 +1,3 @@
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Settings.cpp WARNING: File for Settings not found: data/TestSettings.xml
Token.cpp ERROR: Location Id was not referenced by this Token.
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
Edge.cpp ERROR: Nodes are not plain copies.
-4
View File
@@ -134,12 +134,8 @@ add_files(
data/search/SearchIndex.cpp
data/search/SearchIndex.h
data/search/SearchNode.cpp
data/search/SearchNode.h
data/search/SearchMatch.cpp
data/search/SearchMatch.h
data/search/SearchResult.cpp
data/search/SearchResult.h
data/type/ArrayModifiedDataType.cpp
data/type/ArrayModifiedDataType.h
@@ -582,6 +582,7 @@ std::vector<std::string> CodeController::getProjectDescription(TokenLocationFile
return std::vector<std::string>();
}
// todo fixme: this split currently prevents the next step from recognizing multi level name hierarchies.
std::vector<std::string> lines = utility::splitToVector(description, "\\n");
size_t startLineNumber = 4;
@@ -590,6 +591,7 @@ std::vector<std::string> CodeController::getProjectDescription(TokenLocationFile
std::string line = "\t" + lines[i];
line = utility::replace(line, "\\t", "\t");
line = utility::replace(line, "\\r", "\r");
size_t pos = 0;
while (pos != std::string::npos)
@@ -602,21 +604,23 @@ std::vector<std::string> CodeController::getProjectDescription(TokenLocationFile
break;
}
std::string tokenName = line.substr(posA + 1, posB - posA - 1);
std::string serializedName = line.substr(posA + 1, posB - posA - 1);
Id tokenId = m_storageAccess->getIdForNodeWithSearchNameHierarchy(NameHierarchy(tokenName));
NameHierarchy nameHierarchy = NameHierarchy::deserialize(serializedName);
Id tokenId = m_storageAccess->getIdForNodeWithNameHierarchy(nameHierarchy);
if (tokenId > 0)
{
line.replace(posA, posB - posA + 1, tokenName);
std::string nameString = nameHierarchy.getQualifiedName();
line.replace(posA, posB - posA + 1, nameString);
locationFile->addTokenLocation(
0, tokenId,
startLineNumber + i, posA + 1,
startLineNumber + i, posA + tokenName.size()
startLineNumber + i, posA + nameString.size()
);
}
pos = posA + tokenName.size();
pos = posA + serializedName.size();
}
lines[i] = line;
+63 -74
View File
@@ -39,8 +39,9 @@ Version Storage::getVersion() const
bool Storage::init()
{
m_commandIndex.addNode(NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_ALL)));
m_commandIndex.addNode(NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_ERROR)));
m_commandIndex.addNode(0, NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_ALL)));
m_commandIndex.addNode(0, NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_ERROR)));
m_commandIndex.finishSetup();
return m_sqliteStorage.init();
}
@@ -54,7 +55,7 @@ void Storage::clear()
void Storage::clearCaches()
{
m_tokenIndex.clear();
m_searchIndex.clear();
m_fileNodeIds.clear();
m_hierarchyCache.clear();
}
@@ -135,11 +136,6 @@ std::vector<FileInfo> Storage::getInfoOnAllFiles() const
return fileInfos;
}
const SearchIndex& Storage::getSearchIndex() const
{
return m_tokenIndex;
}
void Storage::logStats() const
{
std::stringstream ss;
@@ -194,17 +190,6 @@ Id Storage::getIdForNodeWithNameHierarchy(const NameHierarchy& nameHierarchy) co
return m_sqliteStorage.getNodeBySerializedName(NameHierarchy::serialize(nameHierarchy)).id;
}
Id Storage::getIdForNodeWithSearchNameHierarchy(const NameHierarchy& nameHierarchy) const
{
SearchNode* node = m_tokenIndex.getNode(nameHierarchy);
if (node)
{
return node->getFirstTokenId();
}
return 0;
}
Id Storage::getIdForEdge(
Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy
) const
@@ -231,77 +216,80 @@ Node::NodeType Storage::getNodeTypeForNodeWithId(Id nodeId) const
std::vector<SearchMatch> Storage::getAutocompletionMatches(const std::string& query) const
{
if (query.size() == m_cachedQuery.size() + 1 && query.find(m_cachedQuery) == 0 && m_cachedResults.size())
const size_t maxResultCount = 100;
std::vector<SearchResult> results = m_commandIndex.search(query, 0);
utility::append(results, m_searchIndex.search(query, maxResultCount));
std::vector<SearchMatch> matches;
for (size_t i = 0; i < results.size(); i++)
{
m_cachedResults = m_tokenIndex.runFuzzySearchCached(query, m_cachedResults);
}
else
{
m_cachedResults = m_tokenIndex.runFuzzySearch(query);
}
SearchMatch match;
m_cachedQuery = query;
SearchResults results = m_cachedResults;
SearchResults commandResults = m_commandIndex.runFuzzySearch(query);
results.insert(commandResults.begin(), commandResults.end());
std::vector<SearchMatch> matches = SearchIndex::getMatches(results, query);
LOG_INFO_STREAM(<< matches.size() << " matches for \"" << query << "\"");
if (matches.size() > 100)
{
matches.resize(100);
}
for (SearchMatch& match : matches)
{
if (!match.tokenIds.size())
if (results[i].elementIds.size() > 0)
{
match.searchType = SearchMatch::SEARCH_COMMAND;
match.typeName = "command";
continue;
}
Id elementId = *(match.tokenIds.cbegin());
if (m_sqliteStorage.isNode(elementId))
{
StorageNode node = m_sqliteStorage.getNodeById(elementId);
match.nodeType = Node::intToType(node.type);
match.typeName = Node::getTypeString(match.nodeType);
if (intToDefinitionType(node.definitionType) == DEFINITION_NONE && match.nodeType != Node::NODE_UNDEFINED)
StorageNode firstNode(0, 0, "", 0);
for (std::set<Id>::const_iterator itElementIds = results[i].elementIds.begin(); itElementIds != results[i].elementIds.end(); itElementIds++)
{
match.typeName = "undefined " + match.typeName;
Id elementId = *itElementIds;
if (elementId != 0)
{
StorageNode node = m_sqliteStorage.getNodeById(elementId);
match.nameHierarchies.push_back(NameHierarchy::deserialize(node.serializedName));
if (firstNode.id == 0)
{
firstNode = node;
}
}
}
match.text = results[i].text;
match.indices = results[i].indices;
if (firstNode.id != 0)
{
match.nodeType = Node::intToType(firstNode.type);
match.typeName = Node::getTypeString(match.nodeType);
if (intToDefinitionType(firstNode.definitionType) == DEFINITION_NONE && match.nodeType != Node::NODE_UNDEFINED)
{
match.typeName = "undefined " + match.typeName;
}
match.searchType = SearchMatch::SEARCH_TOKEN;
}
else
{
match.searchType = SearchMatch::SEARCH_COMMAND;
match.typeName = "command";
}
}
else
{
match.typeName = Edge::getTypeString(Edge::intToType(m_sqliteStorage.getEdgeById(elementId).type));
}
match.searchType = SearchMatch::SEARCH_TOKEN;
matches.push_back(match);
}
std::sort(matches.begin(), matches.end(), [](SearchMatch a, SearchMatch b){
return b.text.size() > a.text.size();
});
return matches;
}
std::vector<SearchMatch> Storage::getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const
std::vector<SearchMatch> Storage::getSearchMatchesForTokenIds(const std::vector<Id>& elementIds) const
{
// todo: what if all these elements share the same node in the searchindex? in that case there should be only one search match.
std::vector<SearchMatch> matches;
for (Id tokenId : tokenIds)
for (Id elementId : elementIds)
{
SearchMatch match;
if (m_sqliteStorage.isFile(tokenId))
if (m_sqliteStorage.isFile(elementId))
{
match.nodeType = Node::NODE_FILE;
}
else if (m_sqliteStorage.isNode(tokenId))
else if (m_sqliteStorage.isNode(elementId))
{
StorageNode node = m_sqliteStorage.getNodeById(tokenId);
StorageNode node = m_sqliteStorage.getNodeById(elementId);
match.nodeType = Node::intToType(node.type);
}
else
@@ -309,8 +297,9 @@ std::vector<SearchMatch> Storage::getSearchMatchesForTokenIds(const std::vector<
continue;
}
match.tokenIds.insert(tokenId);
match.nameHierarchy = m_tokenIndex.getNameHierarchyForTokenId(tokenId);
NameHierarchy nameHierarchy = NameHierarchy::deserialize(m_sqliteStorage.getNodeById(elementId).serializedName);
match.text = nameHierarchy.getQualifiedName();
match.nameHierarchies.push_back(nameHierarchy.getQualifiedName());
match.searchType = SearchMatch::SEARCH_TOKEN;
matches.push_back(match);
@@ -492,10 +481,9 @@ std::vector<Id> Storage::getTokenIdsForMatches(const std::vector<SearchMatch>& m
std::set<Id> idSet;
for (const SearchMatch& match : matches)
{
SearchNode* searchNode = m_tokenIndex.getNode(match.nameHierarchy);
if (searchNode)
for (size_t i = 0; i < match.nameHierarchies.size(); i++)
{
utility::append(idSet, searchNode->getTokenIds());
idSet.insert(m_sqliteStorage.getNodeBySerializedName(NameHierarchy::serialize(match.nameHierarchies[i])).id);
}
}
@@ -980,8 +968,9 @@ void Storage::buildSearchIndex()
{
for (StorageNode node: m_sqliteStorage.getAllNodes())
{
m_tokenIndex.addTokenId(m_tokenIndex.addNode(NameHierarchy::deserialize(node.serializedName)), node.id);
m_searchIndex.addNode(node.id, NameHierarchy::deserialize(node.serializedName));
}
m_searchIndex.finishSetup();
}
void Storage::buildHierarchyCache()
+3 -8
View File
@@ -7,11 +7,11 @@
#include "utility/file/FilePath.h"
#include "data/access/StorageAccess.h"
#include "data/HierarchyCache.h"
#include "data/graph/token_component/TokenComponentAccess.h"
#include "data/location/TokenLocationCollection.h"
#include "data/parser/ParserClient.h"
#include "data/search/SearchIndex.h"
#include "data/HierarchyCache.h"
#include "data/SqliteStorage.h"
#include "data/parser/ParserClientImpl.h"
@@ -35,7 +35,6 @@ public:
void removeUnusedNames();
std::vector<FileInfo> getInfoOnAllFiles() const;
const SearchIndex& getSearchIndex() const;
void logStats() const;
@@ -46,7 +45,6 @@ public:
// StorageAccess implementation
virtual Id getIdForNodeWithNameHierarchy(const NameHierarchy& nameHierarchy) const;
virtual Id getIdForNodeWithSearchNameHierarchy(const NameHierarchy& nameHierarchy) const;
virtual Id getIdForEdge(
Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy) const;
@@ -56,7 +54,7 @@ public:
virtual Node::NodeType getNodeTypeForNodeWithId(Id nodeId) const;
virtual std::vector<SearchMatch> getAutocompletionMatches(const std::string& query) const;
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& tokenIds) const;
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& elementIds) const;
virtual std::shared_ptr<Graph> getGraphForAll() const;
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(const std::vector<Id>& tokenIds, bool activeOnly) const;
@@ -105,16 +103,13 @@ private:
void log(std::string type, std::string str, const ParseLocation& location) const;
SearchIndex m_tokenIndex;
SearchIndex m_commandIndex;
SearchIndex m_searchIndex;
SqliteStorage m_sqliteStorage;
mutable std::map <FilePath, Id> m_fileNodeIds;
HierarchyCache m_hierarchyCache;
mutable SearchResults m_cachedResults;
mutable std::string m_cachedQuery;
};
#endif // STORAGE_H
-1
View File
@@ -27,7 +27,6 @@ public:
virtual ~StorageAccess();
virtual Id getIdForNodeWithNameHierarchy(const NameHierarchy& nameHierarchy) const = 0;
virtual Id getIdForNodeWithSearchNameHierarchy(const NameHierarchy& nameHierarchy) const = 0;
virtual Id getIdForEdge(
Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy) const = 0;
@@ -43,16 +43,6 @@ Id StorageAccessProxy::getIdForNodeWithNameHierarchy(const NameHierarchy& nameHi
return 0;
}
Id StorageAccessProxy::getIdForNodeWithSearchNameHierarchy(const NameHierarchy& nameHierarchy) const
{
if (hasSubject())
{
return m_subject->getIdForNodeWithSearchNameHierarchy(nameHierarchy);
}
return 0;
}
Id StorageAccessProxy::getIdForEdge(
Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy
) const {
-1
View File
@@ -14,7 +14,6 @@ public:
// StorageAccess implementation
virtual Id getIdForNodeWithNameHierarchy(const NameHierarchy& nameHierarchy) const;
virtual Id getIdForNodeWithSearchNameHierarchy(const NameHierarchy& nameHierarchy) const;
virtual Id getIdForEdge(
Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy) const;
+214 -164
View File
@@ -1,208 +1,258 @@
#include "data/search/SearchIndex.h"
#include <algorithm>
#include <cctype>
#include <ctype.h>
#include "utility/logging/logging.h"
#include "data/search/SearchMatch.h"
std::vector<SearchMatch> SearchIndex::getMatches(
const SearchResults& searchResults,
const std::string& query
){
std::vector<SearchMatch> result;
for (SearchResultsIterator it = searchResults.begin(); it != searchResults.end(); it++)
{
SearchMatch match = it->node->fuzzyMatchData(query, it->parent->getParent());
result.push_back(match);
}
return result;
}
#include "utility/utility.h"
SearchIndex::SearchIndex()
: m_root(nullptr, DELIMITER, 0)
{
clear();
}
SearchIndex::~SearchIndex()
{
}
void SearchIndex::clear()
void SearchIndex::addNode(Id id, const NameHierarchy& nameHierarchy)
{
m_root.m_nodes.clear();
m_dictionary.clear();
m_tokenIds.clear();
}
Node* currentNode = m_root;
size_t SearchIndex::getNodeCount() const
{
return m_root.getNodeCount() - 1;
}
// we don't use the signature here, so elements with the same signature share the same node in the search index.
std::string remaining = nameHierarchy.getQualifiedName();
size_t SearchIndex::getCharCount() const
{
return m_dictionary.getCharCount();
}
size_t SearchIndex::getWordCount() const
{
return m_dictionary.getWordCount();
}
Id SearchIndex::getWordId(const std::string& word)
{
return m_dictionary.getWordId(word);
}
const std::string& SearchIndex::getWord(Id wordId) const
{
return m_dictionary.getWord(wordId);
}
SearchNode* SearchIndex::addNode(NameHierarchy nameHierarchy)
{
std::deque<Id> nameIds;
for (size_t i = 0; i < nameHierarchy.size(); i++)
while (remaining.size() > 0)
{
nameIds.push_back(m_dictionary.getWordId(nameHierarchy[i]->getName()));
}
if (nameIds.size())
{
return m_root.addNodeRecursive(&nameIds, m_dictionary).get();
}
return nullptr;
}
SearchNode* SearchIndex::getNode(const NameHierarchy& nameHierarchy) const
{
std::deque<Id> nameIds = m_dictionary.getWordIdsConst(nameHierarchy);
if (nameIds.size())
{
return m_root.getNodeRecursive(&nameIds).get();
}
return nullptr;
}
SearchNode* SearchIndex::getNode(const std::string& fullName) const
{
std::deque<Id> nameIds = m_dictionary.getWordIdsConst(fullName, DELIMITER);
if (nameIds.size())
{
return m_root.getNodeRecursive(&nameIds).get();
}
return nullptr;
}
SearchNode* SearchIndex::getNode(const SearchNode* searchNode) const
{
if(searchNode == nullptr)
{
return nullptr;
}
std::deque<Id> nameIds = searchNode->getNameIdsRecursive();
if (nameIds.size())
{
return m_root.getNodeRecursive(&nameIds).get();
}
return nullptr;
}
void SearchIndex::removeNode(SearchNode* searchNode)
{
if(searchNode == nullptr)
{
return;
}
SearchNode* parent = searchNode->getParent();
if (!parent)
{
LOG_ERROR_STREAM(<< "SearchNode to be removed has no parent: " << searchNode->getFullName());
return;
}
parent->removeSearchNode(searchNode);
}
bool SearchIndex::removeNodeIfUnreferencedRecursive(SearchNode* searchNode)
{
if(searchNode == nullptr)
{
return false;
}
if (!searchNode->hasTokenIdsRecursive())
{
SearchNode* parent = searchNode->getParent();
removeNode(searchNode);
if (parent && parent != &m_root)
bool matchingEdgeFound = false;
// has edge starting with c?
for (size_t i = 0; i < currentNode->edges.size(); i++)
{
removeNodeIfUnreferencedRecursive(parent);
Edge* currentEdge = currentNode->edges[i];
const std::string& edgeString = currentEdge->s;
int matchCount = 0;
for (size_t j = 0; j < edgeString.size() && j < remaining.size(); j++)
{
if (edgeString[j] != remaining[j])
{
break;
}
matchCount++;
}
if (matchCount != 0)
{
remaining = remaining.substr(matchCount);
if (matchCount < edgeString.size())
{
// split current edge
std::shared_ptr<Node> n = std::make_shared<Node>();
m_nodes.push_back(n);
std::shared_ptr<Edge> e = std::make_shared<Edge>();
m_edges.push_back(e);
n->edges.push_back(e.get());
e->s = edgeString.substr(matchCount);
e->target = currentEdge->target;
currentEdge->s = edgeString.substr(0, matchCount);
currentEdge->target = n.get();
}
currentNode = currentEdge->target;
matchingEdgeFound = true;
break;
}
}
return true;
if (!matchingEdgeFound)
{
std::shared_ptr<Node> n = std::make_shared<Node>();
m_nodes.push_back(n);
std::shared_ptr<Edge> e = std::make_shared<Edge>();
m_edges.push_back(e);
e->s = remaining;
e->target = n.get();
currentNode->edges.push_back(e.get());
currentNode = n.get();
remaining = "";
}
}
return false;
currentNode->elementIds.insert(id);
}
void SearchIndex::addTokenId(SearchNode* node, Id tokenId)
void SearchIndex::finishSetup()
{
if(node == nullptr)
for (size_t i = 0; i < m_root->edges.size(); i++)
{
LOG_ERROR("Node points to nullptr: Can't add tokenid");
return;
populateEdgeGate(m_root->edges[i]);
}
node->addTokenId(tokenId);
m_tokenIds.emplace(tokenId, node);
}
NameHierarchy SearchIndex::getNameHierarchyForTokenId(Id tokenId) const
void SearchIndex::clear()
{
std::map<Id, SearchNode*>::const_iterator it = m_tokenIds.find(tokenId);
m_nodes.clear();
m_edges.clear();
if (it != m_tokenIds.end())
std::shared_ptr<Node> n = std::make_shared<Node>();
m_nodes.push_back(n);
m_root = n.get();
}
std::vector<SearchResult> SearchIndex::search(const std::string& query, size_t maxResultCount) const
{
std::string lowerCaseQuery = "";
for (size_t i = 0; i < query.size(); i++)
{
SearchNode* node = it->second;
return node->getNameHierarchy();
lowerCaseQuery += tolower(query[i]);
}
return NameHierarchy();
Path startPath;
startPath.node = m_root;
std::vector<Path> paths = search(startPath, lowerCaseQuery);
// scoring paths
std::vector<std::pair<float, Path>> scoredPaths;
for (size_t i = 0; i < paths.size(); i++)
{
const std::vector<size_t>& currentIndices = paths[i].indices;
int gapCount = 0;
for (size_t j = 1; j < currentIndices.size(); j++)
{
if (currentIndices[j] - currentIndices[j-1] > 1)
{
gapCount++;
}
}
float score = (1.0f / (gapCount + 1)) + (1.0f / (paths[i].text.size() + 1));
scoredPaths.push_back(std::make_pair(score, paths[i]));
}
// sorting paths
std::sort(scoredPaths.begin(), scoredPaths.end(), [](
std::pair<float, Path> a,
std::pair<float, Path> b)
{
return b.first < a.first;
}
);
// preparing results
std::vector<SearchResult> searchResults;
for (size_t i = 0; i < scoredPaths.size() && (maxResultCount == 0 || searchResults.size() < maxResultCount); i++)
{
std::vector<Path> currentPaths;
currentPaths.push_back(scoredPaths[i].second);
while (currentPaths.size() > 0)
{
std::vector<Path> nextPaths;
for (size_t j = 0; j < currentPaths.size(); j++)
{
Path& currentPath = currentPaths[j];
if (currentPath.node->elementIds.size() > 0 && (maxResultCount == 0 || searchResults.size() < maxResultCount))
{
SearchResult result;
result.elementIds = currentPath.node->elementIds;
result.indices = currentPath.indices;
result.text = currentPath.text;
searchResults.push_back(result);
}
for (size_t k = 0; k < currentPath.node->edges.size(); k++)
{
Path nextPath;
nextPath.indices = currentPath.indices;
nextPath.node = currentPath.node->edges[k]->target;
nextPath.text = currentPath.text + currentPath.node->edges[k]->s;
nextPaths.push_back(nextPath);
}
}
currentPaths = nextPaths;
if (!(maxResultCount == 0 || searchResults.size() < maxResultCount))
{
break;
}
}
}
return searchResults;
}
SearchResults SearchIndex::runFuzzySearch(const std::string& query) const
void SearchIndex::populateEdgeGate(Edge* e)
{
return m_root.runFuzzySearch(query);
Node* target = e->target;
for (size_t i = 0; i < target->edges.size(); i++)
{
Edge* targetEdge = target->edges[i];
populateEdgeGate(targetEdge);
utility::append(e->gate, targetEdge->gate);
}
for (size_t i = 0; i < e->s.size(); i++)
{
e->gate.insert(tolower(e->s[i]));
}
}
SearchResults SearchIndex::runFuzzySearchCached(const std::string& query, const SearchResults& searchResults) const
std::vector<SearchIndex::Path> SearchIndex::search(const Path& path, const std::string& remainingQuery) const
{
return m_root.runFuzzySearchCached(query, searchResults);
}
std::vector<Path> results;
std::vector<SearchMatch> SearchIndex::runFuzzySearchAndGetMatches(const std::string& query) const
{
return getMatches(runFuzzySearch(query), query);
}
if (remainingQuery.size() == 0)
{
results.push_back(path);
}
else
{
for (size_t i = 0; i < path.node->edges.size(); i++)
{
const Edge* currentEdge = path.node->edges[i];
const std::string SearchIndex::DELIMITER = "::";
// test if s passes the edge's gate.
bool passesGate = true;
for (size_t j = 0; j < remainingQuery.size(); j++)
{
if (currentEdge->gate.find(tolower(remainingQuery[j])) == currentEdge->gate.end())
{
passesGate = false;
break;
}
}
std::ostream& operator<<(std::ostream& ostream, const SearchIndex& index)
{
ostream << "SearchIndex:\n";
ostream << &index.m_root;
return ostream;
if (passesGate)
{
// consume characters for edge
const std::string& edgeString = currentEdge->s;
std::vector<size_t> currentFoundIds = path.indices;
std::string currentRemainingQuery = remainingQuery;
for (size_t j = 0; j < edgeString.size() && currentRemainingQuery.size() > 0; j++)
{
if (currentRemainingQuery[0] == tolower(edgeString[j]))
{
currentFoundIds.push_back(path.text.size() + j);
currentRemainingQuery = currentRemainingQuery.substr(1);
}
}
Path currentPath;
currentPath.node = currentEdge->target;
currentPath.indices = currentFoundIds;
currentPath.text = path.text + edgeString;
utility::append(results, search(currentPath, currentRemainingQuery));
}
}
}
return results;
}
+44 -37
View File
@@ -1,59 +1,66 @@
#ifndef SEARCH_INDEX_H
#define SEARCH_INDEX_H
#include <ostream>
#include <set>
#include <map>
#include <memory>
#include <vector>
#include "utility/text/Dictionary.h"
#include "utility/types.h"
#include <set>
#include <string>
#include <unordered_set>
#include "data/name/NameHierarchy.h"
#include "data/search/SearchNode.h"
#include "utility/types.h"
struct SearchResult
{
std::string text;
std::set<Id> elementIds;
std::vector<size_t> indices;
};
class SearchIndex
{
public:
static std::vector<SearchMatch> getMatches(const SearchResults& searchResults, const std::string& query);
SearchIndex();
virtual ~SearchIndex();
void addNode(Id id, const NameHierarchy& nameHierarchy);
void finishSetup();
void clear();
size_t getNodeCount() const;
size_t getCharCount() const;
size_t getWordCount() const;
Id getWordId(const std::string& word);
const std::string& getWord(Id wordId) const;
SearchNode* addNode(NameHierarchy nameHierarchy);
SearchNode* getNode(const NameHierarchy& nameHierarchy) const;
SearchNode* getNode(const std::string& fullName) const;
SearchNode* getNode(const SearchNode* searchNode) const;
void removeNode(SearchNode* searchNode);
bool removeNodeIfUnreferencedRecursive(SearchNode* searchNode);
void addTokenId(SearchNode* node, Id tokenId);
NameHierarchy getNameHierarchyForTokenId(Id tokenId) const;
SearchResults runFuzzySearch(const std::string& query) const;
SearchResults runFuzzySearchCached(const std::string& query, const SearchResults& searchResults) const;
std::vector<SearchMatch> runFuzzySearchAndGetMatches(const std::string& query) const;
static const std::string DELIMITER;
// maxResultCount == 0 means "no restriction".
std::vector<SearchResult> search(const std::string& query, size_t maxResultCount) const;
private:
SearchNode m_root;
Dictionary m_dictionary;
struct Node;
struct Edge;
std::map<Id, SearchNode*> m_tokenIds;
struct Node
{
std::set<Id> elementIds;
std::vector<Edge*> edges;
};
friend std::ostream& operator<<(std::ostream& ostream, const SearchIndex& index);
struct Edge
{
Node* target;
std::string s;
std::unordered_set<char> gate;
};
struct Path
{
std::string text;
std::vector<size_t> indices;
Node* node;
};
void populateEdgeGate(Edge* e);
std::vector<Path> search(const Path& path, const std::string& remainingQuery) const;
std::vector<std::shared_ptr<Node>> m_nodes;
std::vector<std::shared_ptr<Edge>> m_edges;
Node* m_root;
};
std::ostream& operator<<(std::ostream& ostream, const SearchIndex& index);
#endif // SEARCH_INDEX_H
+4 -4
View File
@@ -48,7 +48,7 @@ std::string SearchMatch::searchMatchesToString(const std::vector<SearchMatch>& m
SearchMatch SearchMatch::createCommand(CommandType type)
{
SearchMatch match;
match.nameHierarchy = NameHierarchy(getCommandName(type));
match.text = getCommandName(type);
match.typeName = "command";
match.searchType = SEARCH_COMMAND;
return match;
@@ -74,7 +74,7 @@ SearchMatch::SearchMatch()
}
SearchMatch::SearchMatch(const std::string& query)
: nameHierarchy(query)
: text(query)
, typeName("")
, searchType(SEARCH_NONE)
{
@@ -87,7 +87,7 @@ bool SearchMatch::isValid() const
void SearchMatch::print(std::ostream& ostream) const
{
ostream << weight << '\t' << nameHierarchy.getQualifiedName() << std::endl << '\t';
ostream << text << std::endl << '\t';
size_t i = 0;
for (size_t index : indices)
{
@@ -104,7 +104,7 @@ void SearchMatch::print(std::ostream& ostream) const
std::string SearchMatch::getFullName() const
{
return nameHierarchy.getQualifiedName();
return text;
}
std::string SearchMatch::getNodeTypeAsString() const
+3 -6
View File
@@ -44,16 +44,13 @@ struct SearchMatch
std::string getNodeTypeAsString() const;
std::string getSearchTypeName() const;
NameHierarchy nameHierarchy;
std::string text;
std::string typeName;
Node::NodeType nodeType;
SearchType searchType;
std::set<Id> tokenIds;
std::vector<size_t> indices;
size_t weight;
std::vector<NameHierarchy> nameHierarchies;
};
-455
View File
@@ -1,455 +0,0 @@
#include "data/search/SearchNode.h"
#include <algorithm>
#include "utility/text/Dictionary.h"
#include "data/name/NameHierarchy.h"
#include "data/search/SearchIndex.h"
#include "data/search/SearchMatch.h"
#include "data/search/SearchResult.h"
SearchNode::SearchNode(SearchNode* parent, const std::string& name, Id nameId)
: m_parent(parent)
, m_name(name)
, m_nameId(nameId)
{
}
SearchNode::~SearchNode()
{
}
size_t SearchNode::getNodeCount() const
{
size_t count = 1;
for (const std::pair<Id, std::shared_ptr<SearchNode>>& p : m_nodes)
{
count += p.second->getNodeCount();
}
return count;
}
const std::string& SearchNode::getName() const
{
return m_name;
}
NameHierarchy SearchNode::getNameHierarchy() const
{
NameHierarchy nameHierarchy;
const SearchNode* parent = getParent();
if (parent && parent->m_nameId)
{
nameHierarchy = parent->getNameHierarchy();
}
nameHierarchy.push(std::make_shared<NameElement>(getName()));
return nameHierarchy;
}
std::string SearchNode::getFullName() const
{
if (m_parent && m_parent->m_nameId)
{
return m_parent->getFullName() + SearchIndex::DELIMITER + getName();
}
else
{
return getName();
}
}
Id SearchNode::getNameId() const
{
return m_nameId;
}
std::deque<Id> SearchNode::getNameIdsRecursive() const
{
std::deque<Id> ids;
ids.push_front(m_nameId);
SearchNode* parent = m_parent;
while (parent && parent->m_nameId)
{
ids.push_front(parent->getNameId());
parent = parent->getParent();
}
return ids;
}
Id SearchNode::getFirstTokenId() const
{
if (m_tokenIds.size())
{
return *m_tokenIds.begin();
}
return 0;
}
const std::set<Id>& SearchNode::getTokenIds() const
{
return m_tokenIds;
}
bool SearchNode::hasTokenIdsRecursive() const
{
if (m_tokenIds.size())
{
return true;
}
for (const std::pair<Id, std::shared_ptr<SearchNode>>& p : m_nodes)
{
if (p.second->hasTokenIdsRecursive())
{
return true;
}
}
return false;
}
void SearchNode::addTokenId(Id tokenId)
{
m_tokenIds.insert(tokenId);
}
void SearchNode::removeTokenId(Id tokenId)
{
m_tokenIds.erase(tokenId);
}
SearchNode* SearchNode::getParent() const
{
if (m_parent)
{
return m_parent;
}
return nullptr;
}
std::deque<SearchNode*> SearchNode::getParentsWithoutTokenId()
{
std::deque<SearchNode*> nodes;
SearchNode* node = this;
while (node->m_nameId && !node->m_tokenIds.size())
{
nodes.push_front(node);
node = node->m_parent;
}
return nodes;
}
const std::map<Id, std::shared_ptr<SearchNode>>& SearchNode::getChildren() const
{
return m_nodes;
}
SearchResults SearchNode::runFuzzySearch(const std::string& query) const
{
SearchResults result;
for (const std::pair<Id, std::shared_ptr<SearchNode>>& p : m_nodes)
{
FuzzyMap m = p.second->fuzzyMatchRecursive(query, 0, 0, 0);
for (const std::pair<size_t, const SearchNode*>& p2 : m)
{
addResultsRecursive(&result, p2.first, p2.second, p.second.get());
}
}
return result;
}
SearchResults SearchNode::runFuzzySearchCached(const std::string& query, const SearchResults& searchResults) const
{
SearchResults result;
std::set<const SearchNode*> nodes;
for (const SearchResult& r : searchResults)
{
nodes.insert(r.parent);
}
for (const SearchNode* n : nodes)
{
FuzzyMap m = n->fuzzyMatchRecursive(query, 0, 0, 0);
for (const std::pair<size_t, const SearchNode*>& p : m)
{
addResultsRecursive(&result, p.first, p.second, n);
}
}
return result;
}
SearchResults SearchNode::runFuzzySearchOnSelf(const std::string& query) const
{
SearchResults result;
FuzzyMap m = fuzzyMatchRecursive(query, 0, 0, 0);
for (const std::pair<size_t, const SearchNode*>& p : m)
{
addResultsRecursive(&result, p.first, p.second, this);
}
return result;
}
void SearchNode::addResultsRecursive(
SearchResults* results, size_t weight, const SearchNode* node, const SearchNode* parent
) const {
results->insert(SearchResult(weight, node, parent));
for (const std::pair<Id, std::shared_ptr<SearchNode>>& p : node->m_nodes)
{
addResultsRecursive(results, weight, p.second.get(), parent);
}
}
std::shared_ptr<SearchNode> SearchNode::addNodeRecursive(
std::deque<Id>* nameIds, const Dictionary& dictionary
){
Id nameId = nameIds->front();
nameIds->pop_front();
std::shared_ptr<SearchNode> node = getChildWithNameId(nameId);
if (!node)
{
node = std::make_shared<SearchNode>(this, dictionary.getWord(nameId), nameId);
m_nodes.emplace(nameId, node);
}
if (nameIds->size() > 0)
{
return node->addNodeRecursive(nameIds, dictionary);
}
return node;
}
std::shared_ptr<SearchNode> SearchNode::getNodeRecursive(std::deque<Id>* nameIds) const
{
Id nameId = nameIds->front();
nameIds->pop_front();
std::shared_ptr<SearchNode> node = getChildWithNameId(nameId);
if (node)
{
if (!nameIds->size())
{
return node;
}
return node->getNodeRecursive(nameIds);
}
return nullptr;
}
void SearchNode::removeSearchNode(SearchNode* node)
{
std::map<Id, std::shared_ptr<SearchNode>>::iterator it = m_nodes.find(node->getNameId());
if (it != m_nodes.end())
{
m_nodes.erase(it);
}
}
SearchMatch SearchNode::fuzzyMatchData(const std::string& query, const SearchNode* parent) const
{
SearchMatch data;
data.nameHierarchy = getNameHierarchy();
data.tokenIds = m_tokenIds;
data.weight = 0;
size_t pos = 0;
size_t size = 0;
const SearchNode* root = parent;
std::deque<const SearchNode*> nodes = getNodesToParent(parent);
if (!nodes.size())
{
nodes.push_back(this);
root = root->getParent();
}
while (root && root->getNameId())
{
size += root->getName().size() + SearchIndex::DELIMITER.size();
root = root->getParent();
}
for (const SearchNode* node : nodes)
{
std::pair<size_t, size_t> p = node->fuzzyMatch(query, pos, size, &data.indices);
pos = p.first;
data.weight += p.second;
size += node->m_name.size() + SearchIndex::DELIMITER.size();
}
return data;
}
SearchNode::FuzzyMap SearchNode::fuzzyMatchRecursive(
const std::string& query, size_t pos, size_t weight, size_t size) const
{
FuzzyMap result;
std::pair<size_t, size_t> p = fuzzyMatch(query, pos, size);
pos = p.first;
weight += p.second;
if (pos == query.size())
{
result.emplace(weight, this);
return result;
}
for (const std::pair<Id, std::shared_ptr<SearchNode>>& p : m_nodes)
{
FuzzyMap m = p.second->fuzzyMatchRecursive(query, pos, weight, size + m_name.size() + SearchIndex::DELIMITER.size());
result.insert(m.begin(), m.end());
}
return result;
}
std::pair<size_t, size_t> SearchNode::fuzzyMatch(
const std::string query, size_t start, size_t size, std::vector<size_t>* indices) const
{
size_t pos = start;
size_t weight = 0;
size_t matchCount = 0;
size_t ql = query.size();
if (!query.size())
{
return std::pair<size_t, size_t>(pos, weight);
}
if (query[pos] == ':')
{
pos++;
if (indices && size >= 2)
{
indices->push_back(size - 2);
}
if (pos < ql && query[pos] == ':')
{
pos++;
if (indices && size >= 1)
{
indices->push_back(size - 1);
}
}
}
char last = '\0';
size_t nl = m_name.size();
for (size_t i = 0; i < nl; i++)
{
char c = m_name[i];
char next = (i + 1 == nl ? '\0' : m_name[i + 1]);
if (tolower(query[pos]) == tolower(c))
{
weight += std::max<size_t>(100 / sqrt(size + i + 1), 1);
if (matchCount)
{
weight += matchCount * matchCount * 10;
}
if (i == 0)
{
weight += 20;
}
if (last == '_' || next == '_' || next == '\0')
{
weight += 20;
}
else if ((tolower(c) != c && tolower(next) == next) || (tolower(c) == c && tolower(next) != next))
{
weight += 20;
}
matchCount++;
pos++;
if (indices)
{
indices->push_back(size + i);
}
if (pos == ql || query[pos] == ':')
{
break;
}
}
else
{
matchCount = 0;
}
last = c;
}
return std::pair<size_t, size_t>(pos, weight);
}
std::shared_ptr<SearchNode> SearchNode::getChildWithNameId(Id nameId) const
{
std::map<Id, std::shared_ptr<SearchNode>>::const_iterator it = m_nodes.find(nameId);
if (it != m_nodes.end())
{
return it->second;
}
return nullptr;
}
std::deque<const SearchNode*> SearchNode::getNodesToParent(const SearchNode* parent) const
{
std::deque<const SearchNode*> nodes;
const SearchNode* node = this;
while (node->m_nameId && node != parent)
{
nodes.push_front(node);
node = node->m_parent;
}
return nodes;
}
std::ostream& operator<<(std::ostream& ostream, const SearchNode* node)
{
ostream << node->m_name;
for (Id tokenId : node->m_tokenIds)
{
ostream << ' ' << tokenId;
}
ostream << '\n';
for (const std::pair<Id, std::shared_ptr<SearchNode>> p : node->m_nodes)
{
ostream << p.second.get();
}
return ostream;
}
-87
View File
@@ -1,87 +0,0 @@
#ifndef SEARCH_NODE_H
#define SEARCH_NODE_H
#include <deque>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "utility/types.h"
#include "data/search/SearchResult.h"
class Dictionary;
class NameHierarchy;
class SearchIndex;
struct SearchMatch;
class SearchNode
{
public:
SearchNode(SearchNode* parent, const std::string& name, Id nameId);
~SearchNode();
size_t getNodeCount() const;
const std::string& getName() const;
NameHierarchy getNameHierarchy() const;
std::string getFullName() const;
Id getNameId() const;
std::deque<Id> getNameIdsRecursive() const;
Id getFirstTokenId() const;
const std::set<Id>& getTokenIds() const;
bool hasTokenIdsRecursive() const;
void addTokenId(Id tokenId);
void removeTokenId(Id tokenId);
SearchNode* getParent() const;
std::deque<SearchNode*> getParentsWithoutTokenId();
const std::map<Id, std::shared_ptr<SearchNode>>& getChildren() const;
SearchResults runFuzzySearch(const std::string& query) const;
SearchResults runFuzzySearchCached(const std::string& query, const SearchResults& searchResults) const;
SearchResults runFuzzySearchOnSelf(const std::string& query) const;
void addResultsRecursive(SearchResults* results, size_t weight, const SearchNode* node, const SearchNode* parent) const;
private:
typedef std::multimap<size_t, const SearchNode*> FuzzyMap;
typedef FuzzyMap::const_iterator FuzzyMapIterator;
// Accessed by SearchIndex
std::shared_ptr<SearchNode> addNodeRecursive(std::deque<Id>* nameIds, const Dictionary& dictionary);
std::shared_ptr<SearchNode> getNodeRecursive(std::deque<Id>* nameIds) const;
void removeSearchNode(SearchNode* node);
SearchMatch fuzzyMatchData(const std::string& query, const SearchNode* parent) const;
friend class SearchIndex;
FuzzyMap fuzzyMatchRecursive(const std::string& query, size_t pos, size_t weight, size_t size) const;
std::pair<size_t, size_t> fuzzyMatch(
const std::string query, size_t start, size_t size, std::vector<size_t>* indices = nullptr) const;
std::shared_ptr<SearchNode> getChildWithNameId(Id nameId) const;
std::deque<const SearchNode*> getNodesToParent(const SearchNode* parent) const;
std::map<Id, std::shared_ptr<SearchNode>> m_nodes;
SearchNode* m_parent;
std::set<Id> m_tokenIds;
const std::string& m_name;
const Id m_nameId;
friend std::ostream& operator<<(std::ostream& ostream, const SearchNode* node);
};
std::ostream& operator<<(std::ostream& ostream, const SearchNode* node);
#endif // SEARCH_NODE_H
-34
View File
@@ -1,34 +0,0 @@
#include "data/search/SearchResult.h"
#include "utility/utilityString.h"
#include "data/search/SearchNode.h"
SearchResult::SearchResult()
{
}
SearchResult::SearchResult(size_t weight, const SearchNode* node, const SearchNode* parent)
: weight(weight)
, node(node)
, parent(parent)
{
}
bool SearchResult::operator()(const SearchResult& lhs, const SearchResult& rhs) const
{
if (lhs.weight != rhs.weight)
{
return lhs.weight > rhs.weight;
}
std::string lhsLow = utility::toLowerCase(lhs.node->getFullName());
std::string rhsLow = utility::toLowerCase(rhs.node->getFullName());
if (lhsLow != rhsLow)
{
return lhsLow < rhsLow;
}
return lhs.node->getFirstTokenId() < rhs.node->getFirstTokenId();
}
-24
View File
@@ -1,24 +0,0 @@
#ifndef SEARCH_RESULT_H
#define SEARCH_RESULT_H
#include <set>
#include <stddef.h>
class SearchNode;
struct SearchResult
{
SearchResult();
SearchResult(size_t weight, const SearchNode* node, const SearchNode* parent);
bool operator()(const SearchResult& lhs, const SearchResult& rhs) const;
size_t weight;
const SearchNode* node;
const SearchNode* parent;
};
typedef std::set<SearchResult, SearchResult> SearchResults;
typedef SearchResults::const_iterator SearchResultsIterator;
#endif // SEARCH_RESULT_H
+10
View File
@@ -5,6 +5,7 @@
#include <deque>
#include <set>
#include <time.h>
#include <unordered_set>
#include "boost/date_time/posix_time/posix_time.hpp"
@@ -30,6 +31,9 @@ namespace utility
template<typename T>
void append(std::set<T>& a, const std::set<T>& b);
template<typename T>
void append(std::unordered_set<T>& a, const std::unordered_set<T>& b);
template<typename T>
std::vector<T> toVector(const std::deque<T>& d);
@@ -76,6 +80,12 @@ void utility::append(std::set<T>& a, const std::set<T>& b)
a.insert(b.begin(), b.end());
}
template<typename T>
void utility::append(std::unordered_set<T>& a, const std::unordered_set<T>& b)
{
a.insert(b.begin(), b.end());
}
template<typename T>
std::vector<T> utility::toVector(const std::deque<T>& d)
{
+5 -5
View File
@@ -396,7 +396,7 @@ void QtSmartSearchBox::onTextEdited(const QString& text)
}
}
if (match.nameHierarchy.size() && !m_allowMultipleElements)
if (match.text.size() && !m_allowMultipleElements)
{
if (m_matches.size())
{
@@ -415,7 +415,7 @@ void QtSmartSearchBox::onTextEdited(const QString& text)
layoutElements();
}
if (match.nameHierarchy.size() || m_elements.size())
if (match.text.size() || m_elements.size())
{
requestAutoCompletions();
}
@@ -446,7 +446,7 @@ void QtSmartSearchBox::onAutocompletionActivated(const SearchMatch& match)
{
addMatchAndUpdate(match);
if (match.nameHierarchy.size())
if (match.text.size())
{
search();
}
@@ -516,7 +516,7 @@ void QtSmartSearchBox::moveCursorTo(int target)
void QtSmartSearchBox::addMatch(const SearchMatch& match)
{
if (!match.nameHierarchy.size())
if (!match.text.size())
{
return;
}
@@ -543,7 +543,7 @@ void QtSmartSearchBox::addMatch(const SearchMatch& match)
void QtSmartSearchBox::addMatchAndUpdate(const SearchMatch& match)
{
if (match.nameHierarchy.size())
if (match.text.size())
{
m_oldText.clear();
clearLineEdit();
+52 -259
View File
@@ -3,302 +3,95 @@
#include "utility/utilityString.h"
#include "data/search/SearchIndex.h"
#include "data/search/SearchMatch.h"
class SearchIndexTestSuite : public CxxTest::TestSuite
{
public:
void test_add_node()
void test_search_index_finds_id_of_element_added()
{
SearchIndex index;
SearchNode* node = index.addNode(createNameHierarchy("util"));
index.addNode(1, NameHierarchy::deserialize("foo\tvoid\r() const"));
index.finishSetup();
std::vector<SearchResult> results = index.search("oo", 0);
TS_ASSERT(node);
TS_ASSERT_EQUALS("util", node->getName());
TS_ASSERT_EQUALS("util", node->getFullName());
TS_ASSERT(node->getNameId());
TS_ASSERT(!node->getFirstTokenId());
TS_ASSERT(node->getParent());
TS_ASSERT(!node->getParent()->getNameId());
TS_ASSERT_EQUALS(1, results.size());
TS_ASSERT_EQUALS(1, results[0].elementIds.size());
TS_ASSERT_DIFFERS(results[0].elementIds.end(), results[0].elementIds.find(1));
}
void test_get_node()
void test_search_index_finds_correct_indices_for_query()
{
SearchIndex index;
index.addNode(createNameHierarchy("util"));
SearchNode* node = index.getNode("util");
index.addNode(1, NameHierarchy::deserialize("foo\tvoid\r() const"));
index.finishSetup();
std::vector<SearchResult> results = index.search("oo", 0);
TS_ASSERT(node);
TS_ASSERT_EQUALS("util", node->getName());
TS_ASSERT_EQUALS("util", node->getFullName());
TS_ASSERT(node->getNameId());
TS_ASSERT(!node->getFirstTokenId());
TS_ASSERT(node->getParent());
TS_ASSERT(!node->getParent()->getNameId());
node = index.getNode("math");
TS_ASSERT(!node);
TS_ASSERT_EQUALS(1, results.size());
TS_ASSERT_EQUALS(2, results[0].indices.size());
TS_ASSERT_EQUALS(1, results[0].indices[0]);
TS_ASSERT_EQUALS(2, results[0].indices[1]);
}
void test_add_hierarchy_node()
void test_search_index_finds_ids_for_ambiguous_query()
{
SearchIndex index;
SearchNode* node = index.addNode(createNameHierarchy("util::math::pow"));
index.addNode(1, NameHierarchy::deserialize("for\tvoid\r() const"));
index.addNode(2, NameHierarchy::deserialize("fos\tvoid\r() const"));
index.finishSetup();
std::vector<SearchResult> results = index.search("fo", 0);
TS_ASSERT(node);
TS_ASSERT_EQUALS("pow", node->getName());
TS_ASSERT_EQUALS("util::math::pow", node->getFullName());
TS_ASSERT(node->getNameId());
TS_ASSERT(!node->getFirstTokenId());
TS_ASSERT(node->getParent());
TS_ASSERT_EQUALS("math", node->getParent()->getName());
TS_ASSERT(node->getParent()->getParent());
TS_ASSERT_EQUALS("util", node->getParent()->getParent()->getName());
TS_ASSERT_EQUALS(2, results.size());
TS_ASSERT_EQUALS(1, results[0].elementIds.size());
TS_ASSERT_DIFFERS(results[0].elementIds.end(), results[0].elementIds.find(1));
TS_ASSERT_EQUALS(1, results[1].elementIds.size());
TS_ASSERT_DIFFERS(results[1].elementIds.end(), results[1].elementIds.find(2));
}
void test_reuse_hierarchy_node()
void test_search_index_does_not_find_anything_after_clear()
{
SearchIndex index;
SearchNode* node1 = index.addNode(createNameHierarchy("math::pow"));
SearchNode* node2 = index.addNode(createNameHierarchy("math::floor"));
TS_ASSERT(node1);
TS_ASSERT(node2);
TS_ASSERT_EQUALS("pow", node1->getName());
TS_ASSERT_EQUALS("floor", node2->getName());
TS_ASSERT_EQUALS(node1->getParent(), node2->getParent());
}
void test_remove_nodes()
{
SearchIndex index;
index.addNode(createNameHierarchy("util::math::pow"));
index.addNode(createNameHierarchy("util::math::floor"));
index.removeNode(index.getNode("util::math::pow"));
TS_ASSERT(!index.getNode("util::math::pow"));
TS_ASSERT(index.getNode("util::math::floor"));
TS_ASSERT(index.getNode("util::math"));
index.removeNode(index.getNode("util::math"));
TS_ASSERT(!index.getNode("util::math::floor"));
TS_ASSERT(!index.getNode("util::math"));
TS_ASSERT(index.getNode("util"));
}
void test_remove_unreferenced_nodes()
{
SearchIndex index;
SearchNode* node1 = index.addNode(createNameHierarchy("util::math::pow"));
SearchNode* node2 = index.addNode(createNameHierarchy("util::math::floor"));
node1->addTokenId(1);
node2->addTokenId(2);
TS_ASSERT(index.getNode("util")->hasTokenIdsRecursive());
TS_ASSERT(!index.removeNodeIfUnreferencedRecursive(index.getNode("util")));
TS_ASSERT(!index.removeNodeIfUnreferencedRecursive(index.getNode("util::math")));
TS_ASSERT(!index.removeNodeIfUnreferencedRecursive(index.getNode("util::math::pow")));
node1->removeTokenId(1);
TS_ASSERT(index.removeNodeIfUnreferencedRecursive(index.getNode("util::math::pow")));
TS_ASSERT(!index.getNode("util::math::pow"));
TS_ASSERT(index.getNode("util::math"));
TS_ASSERT(index.getNode("util"));
node2->removeTokenId(2);
TS_ASSERT(index.removeNodeIfUnreferencedRecursive(index.getNode("util::math")));
TS_ASSERT(!index.getNode("util::math"));
TS_ASSERT(!index.getNode("util"));
}
void test_clear()
{
SearchIndex index;
index.addNode(createNameHierarchy("math"));
index.addNode(createNameHierarchy("string"));
TS_ASSERT(index.getNode("math"));
index.addNode(1, NameHierarchy::deserialize("foo\tvoid\r() const"));
index.finishSetup();
index.clear();
std::vector<SearchResult> results = index.search("oo", 0);
TS_ASSERT(!index.getNode("math"));
TS_ASSERT(!index.getNode("string"));
TS_ASSERT_EQUALS(0, results.size());
}
void test_fuzzy_matching()
void test_search_index_does_not_find_all_results_when_max_amount_is_limited()
{
SearchIndex index;
index.addNode(createNameHierarchy("util"));
index.addNode(createNameHierarchy("math"));
index.addNode(createNameHierarchy("string"));
index.addNode(1, NameHierarchy::deserialize("foo1\tvoid\r() const"));
index.addNode(2, NameHierarchy::deserialize("foo2\tvoid\r() const"));
index.finishSetup();
std::vector<SearchResult> results = index.search("oo", 1);
std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("u");
TS_ASSERT_EQUALS(1, matches.size());
TS_ASSERT_EQUALS("util", matches[0].getFullName());
TS_ASSERT_EQUALS(1, matches[0].indices.size());
TS_ASSERT_EQUALS(0, matches[0].indices[0]);
matches = index.runFuzzySearchAndGetMatches("");
TS_ASSERT_EQUALS(3, matches.size());
TS_ASSERT_EQUALS("math", matches[0].getFullName());
TS_ASSERT_EQUALS("string", matches[1].getFullName());
TS_ASSERT_EQUALS("util", matches[2].getFullName());
TS_ASSERT_EQUALS(0, matches[0].weight);
TS_ASSERT_EQUALS(0, matches[1].weight);
TS_ASSERT_EQUALS(0, matches[2].weight);
TS_ASSERT_EQUALS(1, results.size());
}
void test_fuzzy_matching_is_case_insensitive()
void test_search_index_query_is_case_insensitive()
{
SearchIndex index;
index.addNode(createNameHierarchy("util"));
index.addNode(createNameHierarchy("MATH"));
index.addNode(1, NameHierarchy::deserialize("foo1\tvoid\r() const"));
index.addNode(2, NameHierarchy::deserialize("FOO2\tvoid\r() const"));
index.finishSetup();
std::vector<SearchResult> results = index.search("oo", 0);
std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("t");
TS_ASSERT_EQUALS(2, matches.size());
TS_ASSERT_EQUALS("util", matches[0].getFullName());
TS_ASSERT_EQUALS("MATH", matches[1].getFullName());
matches = index.runFuzzySearchAndGetMatches("T");
TS_ASSERT_EQUALS(2, matches.size());
TS_ASSERT_EQUALS("util", matches[0].getFullName());
TS_ASSERT_EQUALS("MATH", matches[1].getFullName());
TS_ASSERT_EQUALS(2, results.size());
}
void test_fuzzy_matching_wheighs_by_distance_and_alphabet()
void test_search_index_rates_higher_on_consecutive_letters()
{
SearchIndex index;
index.addNode(createNameHierarchy("util"));
index.addNode(createNameHierarchy("math"));
index.addNode(createNameHierarchy("string"));
index.addNode(1, NameHierarchy::deserialize("oaabbcc\tvoid\r() const"));
index.addNode(2, NameHierarchy::deserialize("ocbcabc\tvoid\r() const"));
index.finishSetup();
std::vector<SearchResult> results = index.search("abc", 0);
std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("t");
TS_ASSERT_EQUALS(3, matches.size());
TS_ASSERT_EQUALS("string", matches[0].getFullName());
TS_ASSERT_EQUALS("util", matches[1].getFullName());
TS_ASSERT_EQUALS("math", matches[2].getFullName());
TS_ASSERT_EQUALS(1, matches[0].indices.size());
TS_ASSERT_EQUALS(1, matches[0].indices[0]);
TS_ASSERT_EQUALS(1, matches[1].indices.size());
TS_ASSERT_EQUALS(1, matches[1].indices[0]);
TS_ASSERT_EQUALS(1, matches[2].indices.size());
TS_ASSERT_EQUALS(2, matches[2].indices[0]);
}
void test_fuzzy_matching_wheighs_higher_by_uppercase()
{
SearchIndex index;
index.addNode(createNameHierarchy("uTil"));
index.addNode(createNameHierarchy("string"));
std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("t");
TS_ASSERT_EQUALS(2, matches.size());
TS_ASSERT_EQUALS("uTil", matches[0].getFullName());
TS_ASSERT_EQUALS("string", matches[1].getFullName());
}
void test_fuzzy_matching_wheighs_higher_on_consecutive_letters()
{
SearchIndex index;
index.addNode(createNameHierarchy("oaabbcc"));
index.addNode(createNameHierarchy("ocbcabc"));
std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("abc");
TS_ASSERT_EQUALS(2, matches.size());
TS_ASSERT_EQUALS("ocbcabc", matches[0].getFullName());
TS_ASSERT_EQUALS("oaabbcc", matches[1].getFullName());
}
void test_fuzzy_matching_in_hierarchy()
{
SearchIndex index;
index.addNode(createNameHierarchy("util::math::ceil"));
index.addNode(createNameHierarchy("util::math::floor"));
index.addNode(createNameHierarchy("util::string::concat"));
std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("t");
TS_ASSERT_EQUALS(6, matches.size());
TS_ASSERT_EQUALS("util", matches[0].getFullName());
TS_ASSERT_EQUALS("util::math", matches[1].getFullName());
TS_ASSERT_EQUALS("util::math::ceil", matches[2].getFullName());
TS_ASSERT_EQUALS("util::math::floor", matches[3].getFullName());
TS_ASSERT_EQUALS("util::string", matches[4].getFullName());
TS_ASSERT_EQUALS("util::string::concat", matches[5].getFullName());
matches = index.runFuzzySearchAndGetMatches("uml");
TS_ASSERT_EQUALS(2, matches.size());
TS_ASSERT_EQUALS("util::math::ceil", matches[0].getFullName());
TS_ASSERT_EQUALS("util::math::floor", matches[1].getFullName());
}
void test_fuzzy_matching_in_hierarchy_respects_collin()
{
SearchIndex index;
index.addNode(createNameHierarchy("util::math::ceil"));
index.addNode(createNameHierarchy("util::math::floor"));
index.addNode(createNameHierarchy("util::string::concat"));
std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("u:i");
TS_ASSERT_EQUALS(3, matches.size());
TS_ASSERT_EQUALS("util::string", matches[0].getFullName());
TS_ASSERT_EQUALS("util::string::concat", matches[1].getFullName());
TS_ASSERT_EQUALS("util::math::ceil", matches[2].getFullName());
matches = index.runFuzzySearchAndGetMatches("u:t:i");
TS_ASSERT_EQUALS(1, matches.size());
TS_ASSERT_EQUALS("util::math::ceil", matches[0].getFullName());
}
void test_fuzzy_matching_in_hierarchy_weighs_front_letters_higher()
{
SearchIndex index;
index.addNode(createNameHierarchy("abc::dfe::ghi"));
index.addNode(createNameHierarchy("abc::hgi"));
std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("g");
TS_ASSERT_EQUALS(2, matches.size());
TS_ASSERT_EQUALS("abc::dfe::ghi", matches[0].getFullName());
TS_ASSERT_EQUALS("abc::hgi", matches[1].getFullName());
}
private:
NameHierarchy createNameHierarchy(std::string s) const
{
NameHierarchy nameHierarchy;
for (std::string element: utility::splitToVector(s, "::"))
{
nameHierarchy.push(std::make_shared<NameElement>(element));
}
return nameHierarchy;
TS_ASSERT_EQUALS(2, results.size());
TS_ASSERT_EQUALS("ocbcabc", results[0].text);
TS_ASSERT_EQUALS("oaabbcc", results[1].text);
}
};
+2 -20
View File
@@ -97,7 +97,6 @@ public:
TS_ASSERT_EQUALS(storage.getNodeCount(), 3);
TS_ASSERT_EQUALS(storage.getEdgeCount(), 2);
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 4);
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 3);
std::set<FilePath> files;
files.insert(FilePath(m_filePath));
@@ -105,8 +104,7 @@ public:
TS_ASSERT_EQUALS(storage.getNodeCount(), 0);
TS_ASSERT_EQUALS(storage.getEdgeCount(), 0);
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 0);
TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 0);*/
TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 0);*/
}
void test_storage_clears_unreferenced_single_file_data_of_multi_file_storage()
@@ -128,7 +126,6 @@ public:
//TS_ASSERT_EQUALS(storage.getNodeCount(), 6);
//TS_ASSERT_EQUALS(storage.getEdgeCount(), 5);
//TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 9);
//TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 6);
//std::set<FilePath> files;
//files.insert(FilePath("file.cpp"));
@@ -136,8 +133,7 @@ public:
//TS_ASSERT_EQUALS(storage.getNodeCount(), 3);
//TS_ASSERT_EQUALS(storage.getEdgeCount(), 2);
//TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 4);
//TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 3);
//TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 4);*/
}
void test_storage_clears_referenced_single_file_data_of_multi_file_storage()
@@ -159,7 +155,6 @@ public:
//TS_ASSERT_EQUALS(storage.getNodeCount(), 5);
//TS_ASSERT_EQUALS(storage.getEdgeCount(), 5);
//TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 9);
//TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 5);
//std::set<FilePath> files;
//files.insert(FilePath("file.h"));
@@ -168,7 +163,6 @@ public:
//TS_ASSERT_EQUALS(storage.getNodeCount(), 4);
//TS_ASSERT_EQUALS(storage.getEdgeCount(), 3);
//TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 5);
//TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 4);
}
void test_storage_clears_multi_file_data_of_multi_file_storage()
@@ -190,7 +184,6 @@ public:
//TS_ASSERT_EQUALS(storage.getNodeCount(), 5);
//TS_ASSERT_EQUALS(storage.getEdgeCount(), 5);
//TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 9);
//TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 5);
//std::set<FilePath> filePaths;
//filePaths.insert(FilePath("file.cpp"));
@@ -200,7 +193,6 @@ public:
//TS_ASSERT_EQUALS(storage.getNodeCount(), 0);
//TS_ASSERT_EQUALS(storage.getEdgeCount(), 0);
//TS_ASSERT_EQUALS(storage.tokenLocationCollection().getTokenLocations().size(), 0);
//TS_ASSERT_EQUALS(storage.searchIndex().getNodeCount(), 0);
}
void test_storage_finds_and_removes_depending_file_nodes()
@@ -248,11 +240,6 @@ private:
return getTokenLocationsForTokenIds(tokenIds);
}
//const std::string& getWord(Id wordId) const
//{
// return getSearchIndex().getWord(wordId);
//}
//const size_t getNodeCount() const
//{
// return getGraph().getNodeCount();
@@ -263,11 +250,6 @@ private:
// return getGraph().getEdgeCount();
//}
const SearchIndex& searchIndex() const
{
return getSearchIndex();
}
Id getEdgeId(Edge::EdgeType type, const NameHierarchy& fromName, const NameHierarchy& toName) const
{
NameHierarchy from;