logic: improved codeview performance
* reduced database queries necessary for creating code snippets in the codeview.
This commit is contained in:
@@ -517,24 +517,31 @@ std::shared_ptr<TokenLocationFile> SqliteStorage::getTokenLocationsForFile(const
|
||||
}
|
||||
|
||||
std::vector<StorageSourceLocation> SqliteStorage::getTokenLocationsForElementId(const Id elementId) const
|
||||
{
|
||||
std::vector<Id> elementIds {elementId};
|
||||
return getTokenLocationsForElementIds(elementIds);
|
||||
}
|
||||
|
||||
std::vector<StorageSourceLocation> SqliteStorage::getTokenLocationsForElementIds(const std::vector<Id> elementIds) const
|
||||
{
|
||||
std::vector<StorageSourceLocation> locations;
|
||||
|
||||
CppSQLite3Query q = m_database.execQuery((
|
||||
"SELECT id, file_node_id, start_line, start_column, end_line, end_column, is_scope FROM source_location WHERE element_id == " + std::to_string(elementId) + ";"
|
||||
"SELECT id, element_id, file_node_id, start_line, start_column, end_line, end_column, is_scope FROM source_location WHERE element_id IN (" + utility::join(utility::toStrings(elementIds), ',') + ");"
|
||||
).c_str());
|
||||
|
||||
while (!q.eof())
|
||||
{
|
||||
const Id id = q.getIntField(0, 0);
|
||||
const Id fileNodeId = q.getIntField(1, 0);
|
||||
const int startLineNumber = q.getIntField(2, -1);
|
||||
const int startColNumber = q.getIntField(3, -1);
|
||||
const int endLineNumber = q.getIntField(4, -1);
|
||||
const int endColNumber = q.getIntField(5, -1);
|
||||
const int isScope = q.getIntField(6, -1);
|
||||
const Id elementId = q.getIntField(1, 0);
|
||||
const Id fileNodeId = q.getIntField(2, 0);
|
||||
const int startLineNumber = q.getIntField(3, -1);
|
||||
const int startColNumber = q.getIntField(4, -1);
|
||||
const int endLineNumber = q.getIntField(5, -1);
|
||||
const int endColNumber = q.getIntField(6, -1);
|
||||
const int isScope = q.getIntField(7, -1);
|
||||
|
||||
if (id != 0 && fileNodeId != 0 && startLineNumber != -1 && startColNumber != -1 && endLineNumber != -1 && endColNumber != -1 && isScope != -1)
|
||||
if (id != 0 && elementId != 0 && fileNodeId != 0 && startLineNumber != -1 && startColNumber != -1 && endLineNumber != -1 && endColNumber != -1 && isScope != -1)
|
||||
{
|
||||
locations.push_back(StorageSourceLocation(
|
||||
id, elementId, fileNodeId, startLineNumber, startColNumber, endLineNumber, endColNumber, isScope
|
||||
|
||||
@@ -86,6 +86,7 @@ public:
|
||||
StorageSourceLocation getSourceLocationById(const Id id) const;
|
||||
std::shared_ptr<TokenLocationFile> getTokenLocationsForFile(const FilePath& filePath) const;
|
||||
std::vector<StorageSourceLocation> getTokenLocationsForElementId(const Id elementId) const;
|
||||
std::vector<StorageSourceLocation> getTokenLocationsForElementIds(const std::vector<Id> elementIds) const;
|
||||
|
||||
Id getElementIdByLocationId(Id locationId) const;
|
||||
|
||||
|
||||
+41
-110
@@ -11,6 +11,7 @@
|
||||
#include "utility/utility.h"
|
||||
#include "utility/utilityString.h"
|
||||
#include "utility/Version.h"
|
||||
#include "utility/Cache.h"
|
||||
|
||||
#include "data/graph/token_component/TokenComponentAggregation.h"
|
||||
#include "data/graph/token_component/TokenComponentSignature.h"
|
||||
@@ -957,37 +958,52 @@ std::shared_ptr<TokenLocationCollection> Storage::getTokenLocationsForTokenIds(c
|
||||
{
|
||||
std::shared_ptr<TokenLocationCollection> collection = std::make_shared<TokenLocationCollection>();
|
||||
|
||||
for (Id elementId: tokenIds)
|
||||
std::vector<Id> fileIds;
|
||||
std::vector<Id> nonFileIds;
|
||||
for (size_t i = 0; i < tokenIds.size(); i++)
|
||||
{
|
||||
if (m_sqliteStorage.isFile(elementId))
|
||||
if (m_sqliteStorage.isFile(tokenIds[i]))
|
||||
{
|
||||
StorageFile storageFile = m_sqliteStorage.getFileById(elementId);
|
||||
collection->addTokenLocationFileAsPlainCopy(m_sqliteStorage.getTokenLocationsForFile(storageFile.filePath).get());
|
||||
fileIds.push_back(tokenIds[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<StorageSourceLocation> locations = m_sqliteStorage.getTokenLocationsForElementId(elementId);
|
||||
for (size_t i = 0; i < locations.size(); i++)
|
||||
{
|
||||
// TODO: optimize: fileNodeId to name in a separate map
|
||||
const StorageSourceLocation& location = locations[i];
|
||||
StorageFile storageFile = m_sqliteStorage.getFileById(location.fileNodeId);
|
||||
nonFileIds.push_back(tokenIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TokenLocation* loc = collection->addTokenLocation(
|
||||
location.id,
|
||||
location.elementId,
|
||||
storageFile.filePath,
|
||||
location.startLine,
|
||||
location.startCol,
|
||||
location.endLine,
|
||||
location.endCol
|
||||
);
|
||||
for (Id fileId: fileIds)
|
||||
{
|
||||
StorageFile storageFile = m_sqliteStorage.getFileById(fileId);
|
||||
collection->addTokenLocationFileAsPlainCopy(m_sqliteStorage.getTokenLocationsForFile(storageFile.filePath).get());
|
||||
}
|
||||
|
||||
if (loc)
|
||||
{
|
||||
loc->setType(location.isScope ? TokenLocation::LOCATION_SCOPE : TokenLocation::LOCATION_TOKEN);
|
||||
}
|
||||
}
|
||||
Cache<Id, std::string> filePathCache(
|
||||
[this](Id id) -> std::string
|
||||
{
|
||||
return m_sqliteStorage.getFileById(id).filePath;
|
||||
}
|
||||
);
|
||||
|
||||
std::vector<StorageSourceLocation> locations = m_sqliteStorage.getTokenLocationsForElementIds(nonFileIds);
|
||||
for (size_t i = 0; i < locations.size(); i++)
|
||||
{
|
||||
const StorageSourceLocation& location = locations[i];
|
||||
std::string filePath = filePathCache.getValue(location.fileNodeId);
|
||||
|
||||
TokenLocation* loc = collection->addTokenLocation(
|
||||
location.id,
|
||||
location.elementId,
|
||||
filePath,
|
||||
location.startLine,
|
||||
location.startCol,
|
||||
location.endLine,
|
||||
location.endCol
|
||||
);
|
||||
|
||||
if (loc)
|
||||
{
|
||||
loc->setType(location.isScope ? TokenLocation::LOCATION_SCOPE : TokenLocation::LOCATION_TOKEN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1026,57 +1042,7 @@ std::shared_ptr<TokenLocationFile> Storage::getTokenLocationsForLinesInFile(
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
) const
|
||||
{
|
||||
std::shared_ptr<TokenLocationFile> ret = std::make_shared<TokenLocationFile>(filePath);
|
||||
|
||||
std::shared_ptr<TokenLocationFile> locationFile = m_sqliteStorage.getTokenLocationsForFile(filePath);
|
||||
if (!locationFile->getTokenLocationLines().size())
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint endLineNumber = locationFile->getTokenLocationLines().rbegin()->first;
|
||||
std::set<Id> addedLocationIds;
|
||||
for (uint i = firstLineNumber; i <= endLineNumber; i++)
|
||||
{
|
||||
TokenLocationLine* locationLine = locationFile->findTokenLocationLineByNumber(i);
|
||||
if (!locationLine)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (locationLine->getLineNumber() <= lastLineNumber)
|
||||
{
|
||||
locationLine->forEachTokenLocation(
|
||||
[&](TokenLocation* tokenLocation) -> void
|
||||
{
|
||||
const Id tokenId = tokenLocation->getId();
|
||||
if (addedLocationIds.find(tokenId) == addedLocationIds.end())
|
||||
{
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getStartTokenLocation());
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getEndTokenLocation());
|
||||
addedLocationIds.insert(tokenId);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save start locations of TokenLocations that span accross the line range.
|
||||
locationLine->forEachTokenLocation(
|
||||
[&](TokenLocation* tokenLocation) -> void
|
||||
{
|
||||
if (tokenLocation->isEndTokenLocation() &&
|
||||
tokenLocation->getStartTokenLocation()->getLineNumber() < firstLineNumber)
|
||||
{
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getStartTokenLocation());
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getEndTokenLocation());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return m_sqliteStorage.getTokenLocationsForFile(filePath)->getFilteredByLines(firstLineNumber, lastLineNumber);
|
||||
}
|
||||
|
||||
TokenLocationCollection Storage::getErrorTokenLocations(std::vector<std::string>* errorMessages) const
|
||||
@@ -1095,41 +1061,6 @@ TokenLocationCollection Storage::getErrorTokenLocations(std::vector<std::string>
|
||||
return errorCollection;
|
||||
}
|
||||
|
||||
std::shared_ptr<TokenLocationFile> Storage::getTokenLocationOfParentScope(const TokenLocation* child) const
|
||||
{
|
||||
const TokenLocation* parent = child;
|
||||
const FilePath filePath = child->getFilePath();
|
||||
|
||||
std::shared_ptr<TokenLocationFile> locationFile = m_sqliteStorage.getTokenLocationsForFile(filePath); // TODO: sqlite should not know TokenLocationFile!
|
||||
locationFile->forEachStartTokenLocation(
|
||||
[&](TokenLocation* tokenLocation) -> void
|
||||
{
|
||||
if (tokenLocation->getType() == TokenLocation::LOCATION_SCOPE &&
|
||||
(*tokenLocation) < *(child->getStartTokenLocation()) &&
|
||||
(*tokenLocation->getEndTokenLocation()) > *(child->getEndTokenLocation()))
|
||||
{
|
||||
if (parent == child)
|
||||
{
|
||||
parent = tokenLocation;
|
||||
}
|
||||
// since tokenLocation is a start location the > location indicates the scope that is closer to the child.
|
||||
else if ((*tokenLocation) > *parent)
|
||||
{
|
||||
parent = tokenLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
std::shared_ptr<TokenLocationFile> file = std::make_shared<TokenLocationFile>(filePath);
|
||||
if (parent != child)
|
||||
{
|
||||
file->addTokenLocationAsPlainCopy(parent);
|
||||
file->addTokenLocationAsPlainCopy(parent->getOtherTokenLocation());
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
std::shared_ptr<TokenLocationFile> Storage::getCommentLocationsInFile(const FilePath& filePath) const
|
||||
{
|
||||
std::shared_ptr<TokenLocationFile> file = std::make_shared<TokenLocationFile>(filePath);
|
||||
|
||||
@@ -147,7 +147,6 @@ public:
|
||||
) const;
|
||||
|
||||
virtual TokenLocationCollection getErrorTokenLocations(std::vector<std::string>* errorMessages) const;
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationOfParentScope(const TokenLocation* child) const;
|
||||
virtual std::shared_ptr<TokenLocationFile> getCommentLocationsInFile(const FilePath& filePath) const;
|
||||
|
||||
virtual std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const;
|
||||
|
||||
@@ -57,7 +57,6 @@ public:
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber) const = 0;
|
||||
|
||||
virtual TokenLocationCollection getErrorTokenLocations(std::vector<std::string>* errorMessages) const = 0;
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationOfParentScope(const TokenLocation* child) const = 0;
|
||||
virtual std::shared_ptr<TokenLocationFile> getCommentLocationsInFile(const FilePath& filePath) const = 0;
|
||||
|
||||
virtual std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const = 0;
|
||||
|
||||
@@ -245,16 +245,6 @@ TokenLocationCollection StorageAccessProxy::getErrorTokenLocations(std::vector<s
|
||||
return TokenLocationCollection();
|
||||
}
|
||||
|
||||
std::shared_ptr<TokenLocationFile> StorageAccessProxy::getTokenLocationOfParentScope(const TokenLocation* child) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getTokenLocationOfParentScope(child);
|
||||
}
|
||||
|
||||
return std::make_shared<TokenLocationFile>("");
|
||||
}
|
||||
|
||||
std::shared_ptr<TokenLocationFile> StorageAccessProxy::getCommentLocationsInFile(const FilePath& filePath) const
|
||||
{
|
||||
if (hasSubject())
|
||||
|
||||
@@ -46,7 +46,6 @@ public:
|
||||
) const;
|
||||
|
||||
virtual TokenLocationCollection getErrorTokenLocations(std::vector<std::string>* errorMessages) const;
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationOfParentScope(const TokenLocation* child) const;
|
||||
virtual std::shared_ptr<TokenLocationFile> getCommentLocationsInFile(const FilePath& filePath) const;
|
||||
|
||||
virtual std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "data/location/TokenLocationFile.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/types.h"
|
||||
|
||||
#include "data/location/TokenLocation.h"
|
||||
#include "data/location/TokenLocationLine.h"
|
||||
@@ -164,6 +167,60 @@ TokenLocation* TokenLocationFile::addTokenLocationAsPlainCopy(const TokenLocatio
|
||||
return copy;
|
||||
}
|
||||
|
||||
std::shared_ptr<TokenLocationFile> TokenLocationFile::getFilteredByLines(unsigned int firstLineNumber, unsigned int lastLineNumber) const
|
||||
{
|
||||
std::shared_ptr<TokenLocationFile> ret = std::make_shared<TokenLocationFile>(getFilePath().str());
|
||||
|
||||
if (getTokenLocationLines().size() == 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint endLineNumber = getTokenLocationLines().rbegin()->first;
|
||||
std::set<Id> addedLocationIds;
|
||||
for (uint i = firstLineNumber; i <= endLineNumber; i++)
|
||||
{
|
||||
TokenLocationLine* locationLine = findTokenLocationLineByNumber(i);
|
||||
if (!locationLine)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (locationLine->getLineNumber() <= lastLineNumber)
|
||||
{
|
||||
locationLine->forEachTokenLocation(
|
||||
[&](TokenLocation* tokenLocation) -> void
|
||||
{
|
||||
const Id tokenId = tokenLocation->getId();
|
||||
if (addedLocationIds.find(tokenId) == addedLocationIds.end())
|
||||
{
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getStartTokenLocation());
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getEndTokenLocation());
|
||||
addedLocationIds.insert(tokenId);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save start locations of TokenLocations that span accross the line range.
|
||||
locationLine->forEachTokenLocation(
|
||||
[&](TokenLocation* tokenLocation) -> void
|
||||
{
|
||||
if (tokenLocation->isEndTokenLocation() &&
|
||||
tokenLocation->getStartTokenLocation()->getLineNumber() < firstLineNumber)
|
||||
{
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getStartTokenLocation());
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getEndTokenLocation());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
TokenLocationLine* TokenLocationFile::findTokenLocationLine(unsigned int lineNumber) const
|
||||
{
|
||||
TokenLocationLineMapType::const_iterator it = m_lines.find(lineNumber);
|
||||
@@ -199,3 +256,4 @@ std::ostream& operator<<(std::ostream& ostream, const TokenLocationFile& file)
|
||||
});
|
||||
return ostream;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ public:
|
||||
|
||||
TokenLocation* addTokenLocationAsPlainCopy(const TokenLocation* location);
|
||||
|
||||
std::shared_ptr<TokenLocationFile> getFilteredByLines(unsigned int firstLineNumber, unsigned int lastLineNumber) const;
|
||||
|
||||
bool isWholeCopy;
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user