Clang: Add file cache

The database is using file path integer ids to handle file paths because
otherwise we would save many redundant data. This patch is improving it
further with the introduction of a database based file path cache. The
entries are now divided in a directory path and file name. This is quite
handy for directory based file watching.

Change-Id: I03f2e388e43f3d521d6bf8e39dfb95eb2309dc73
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2017-09-21 11:43:59 +02:00
committed by Tim Jenssen
parent 0be8240002
commit d2e15e5f1e
135 changed files with 3458 additions and 1517 deletions

View File

@@ -33,8 +33,15 @@
#include <coreplugin/find/searchresultwindow.h>
#include <extensionsystem/pluginmanager.h>
#include <refactoringdatabaseinitializer.h>
#include <filepathcaching.h>
#include <sqlitedatabase.h>
#include <utils/hostosinfo.h>
#include <QDir>
namespace ClangRefactoring {
namespace {
@@ -54,9 +61,12 @@ class ClangRefactoringPluginData
{
using ProjectUpdater = ClangPchManager::QtCreatorProjectUpdater<ClangPchManager::ProjectUpdater>;
public:
Sqlite::Database database{Utils::PathString{QDir::tempPath() + "/symbol.db"}};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
ClangBackEnd::FilePathCaching filePathCache{database};
RefactoringClient refactoringClient;
ClangBackEnd::RefactoringConnectionClient connectionClient{&refactoringClient};
RefactoringEngine engine{connectionClient.serverProxy(), refactoringClient};
RefactoringEngine engine{connectionClient.serverProxy(), refactoringClient, filePathCache};
QtCreatorSearch qtCreatorSearch{*Core::SearchResultWindow::instance()};
QtCreatorClangQueryFindFilter qtCreatorfindFilter{connectionClient.serverProxy(),
qtCreatorSearch,

View File

@@ -40,14 +40,9 @@ public:
{}
Database &database;
ReadStatement selectLocationsForSymbolLocation{
"SELECT sourceId, line, column FROM locations WHERE symbolId = "
" (SELECT symbolId FROM locations WHERE sourceId="
" (SELECT sourceId FROM sources WHERE sourcePath =?)"
" AND line=? AND column=?) "
"SELECT directoryId, sourceId, line, column FROM locations JOIN sources USING(sourceId) WHERE symbolId = "
" (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND column=?) "
"ORDER BY sourceId, line, column",
database}; // alternatively SELECT l2.symbolid, l2.sourceId, l2.line, l2.column FROM locations AS l2, sources, locations AS l1 ON sources.sourceId = l1.sourceId AND l2.symbolId=l1.symbolId WHERE sourcePath = ? AND l1.line=? AND l1.column=? ORDER BY l2.sourceId, l2.line, l2.column
ReadStatement selectSourcePathForId{
"SELECT sourceId, sourcePath FROM sources WHERE sourceId = ?",
database};
};

View File

@@ -28,8 +28,9 @@
#include "clangqueryhighlighter.h"
#include "clangqueryexamplehighlighter.h"
#include <refactoringconnectionclient.h>
#include <clangrefactoringmessages.h>
#include <filepathcachinginterface.h>
#include <refactoringconnectionclient.h>
namespace ClangRefactoring {
@@ -43,8 +44,8 @@ void RefactoringClient::sourceLocationsForRenamingMessage(
ClangBackEnd::SourceLocationsForRenamingMessage &&message)
{
m_localRenamingCallback(message.symbolName().toQString(),
message.sourceLocations(),
message.textDocumentRevision());
message.sourceLocations(),
message.textDocumentRevision());
m_refactoringEngine->setUsable(true);
}
@@ -122,45 +123,24 @@ void RefactoringClient::setRefactoringConnectionClient(
m_connectionClient = connectionClient;
}
std::unordered_map<uint, QString> RefactoringClient::convertFilePaths(
const ClangBackEnd::FilePathDict &filePaths)
{
using Dict = std::unordered_map<uint, QString>;
Dict qstringFilePaths;
qstringFilePaths.reserve(filePaths.size());
auto convertFilePath = [] (const ClangBackEnd::FilePathDict::value_type &dictonaryEntry) {
return std::make_pair(dictonaryEntry.first,
dictonaryEntry.second.path().toQString());
};
std::transform(filePaths.begin(),
filePaths.end(),
std::inserter(qstringFilePaths, qstringFilePaths.begin()),
convertFilePath);
return qstringFilePaths;
}
void RefactoringClient::addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges)
{
auto filePaths = convertFilePaths(sourceRanges.filePaths());
for (const auto &sourceRangeWithText : sourceRanges.sourceRangeWithTextContainers())
addSearchResult(sourceRangeWithText, filePaths);
addSearchResult(sourceRangeWithText);
}
void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRangeWithText,
std::unordered_map<uint, QString> &filePaths)
void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRangeWithText)
{
m_searchHandle->addResult(filePaths[sourceRangeWithText.fileHash()],
QString(sourceRangeWithText.text()),
{{int(sourceRangeWithText.start().line()),
int(sourceRangeWithText.start().column() - 1),
int(sourceRangeWithText.start().offset())},
{int(sourceRangeWithText.end().line()),
int(sourceRangeWithText.end().column() - 1),
int(sourceRangeWithText.end().offset())}});
auto &filePathCache = m_refactoringEngine->filePathCache();
m_searchHandle->addResult(QString(filePathCache.filePath(sourceRangeWithText.filePathId()).path()),
QString(sourceRangeWithText.text()),
{{int(sourceRangeWithText.start().line()),
int(sourceRangeWithText.start().column() - 1),
int(sourceRangeWithText.start().offset())},
{int(sourceRangeWithText.end().line()),
int(sourceRangeWithText.end().column() - 1),
int(sourceRangeWithText.end().offset())}});
}
void RefactoringClient::setResultCounterAndSendSearchIsFinishedIfFinished()

View File

@@ -66,9 +66,6 @@ public:
bool hasValidLocalRenamingCallback() const;
static std::unordered_map<uint, QString> convertFilePaths(
const std::unordered_map<uint, ClangBackEnd::FilePath> &filePaths);
void setExpectedResultCount(uint count);
uint expectedResultCount() const;
uint resultCounter() const;
@@ -76,8 +73,7 @@ public:
void setRefactoringConnectionClient(ClangBackEnd::RefactoringConnectionClient *connectionClient);
unittest_public:
void addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRange,
std::unordered_map<uint, QString> &filePaths);
void addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRange);
private:
void addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges);

View File

@@ -46,9 +46,11 @@ namespace ClangRefactoring {
using ClangBackEnd::RequestSourceLocationsForRenamingMessage;
RefactoringEngine::RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server,
ClangBackEnd::RefactoringClientInterface &client)
: server(server),
client(client)
ClangBackEnd::RefactoringClientInterface &client,
ClangBackEnd::FilePathCachingInterface &filePathCache)
: m_server(server),
m_client(client),
m_filePathCache(filePathCache)
{
}
@@ -60,7 +62,7 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
setUsable(false);
client.setLocalRenamingCallback(std::move(renameSymbolsCallback));
m_client.setLocalRenamingCallback(std::move(renameSymbolsCallback));
QString filePath = data.filePath().toString();
QTextCursor textCursor = data.cursor();
@@ -79,7 +81,7 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
textCursor.document()->revision());
server.requestSourceLocationsForRenamingMessage(std::move(message));
m_server.requestSourceLocationsForRenamingMessage(std::move(message));
}
void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &)
@@ -89,12 +91,12 @@ void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &)
bool RefactoringEngine::isUsable() const
{
return server.isUsable();
return m_server.isUsable();
}
void RefactoringEngine::setUsable(bool isUsable)
{
server.setUsable(isUsable);
m_server.setUsable(isUsable);
}
} // namespace ClangRefactoring

View File

@@ -25,6 +25,8 @@
#pragma once
#include <filepathcachingfwd.h>
#include <cpptools/refactoringengineinterface.h>
namespace ClangBackEnd {
@@ -37,8 +39,10 @@ namespace ClangRefactoring {
class RefactoringEngine : public CppTools::RefactoringEngineInterface
{
public:
RefactoringEngine(ClangBackEnd::RefactoringServerInterface &server,
ClangBackEnd::RefactoringClientInterface &client);
RefactoringEngine(ClangBackEnd::RefactoringServerInterface &m_server,
ClangBackEnd::RefactoringClientInterface &m_client,
ClangBackEnd::FilePathCachingInterface &filePathCache);
void startLocalRenaming(const CppTools::CursorInEditor &data,
CppTools::ProjectPart *projectPart,
RenameCallback &&renameSymbolsCallback) override;
@@ -47,9 +51,15 @@ public:
bool isUsable() const override;
void setUsable(bool isUsable);
ClangBackEnd::FilePathCachingInterface &filePathCache()
{
return m_filePathCache;
}
private:
ClangBackEnd::RefactoringServerInterface &server;
ClangBackEnd::RefactoringClientInterface &client;
ClangBackEnd::RefactoringServerInterface &m_server;
ClangBackEnd::RefactoringClientInterface &m_client;
ClangBackEnd::FilePathCachingInterface &m_filePathCache;
};
} // namespace ClangRefactoring

View File

@@ -27,39 +27,26 @@
#include <utils/smallstring.h>
#include <cstdint>
#include <filepathid.h>
#include <vector>
#include <tuple>
#include <unordered_map>
namespace ClangRefactoring {
class SourceLocations
struct SourceLocation
{
public:
struct Location
{
Location(qint64 sourceId, qint64 line, qint64 column)
: sourceId(sourceId), line(line), column(column)
{}
SourceLocation(ClangBackEnd::FilePathId filePathId, int line, int column)
: filePathId(filePathId), line(line), column(column)
{}
SourceLocation(int directoryId, int sourceId, int line, int column)
: filePathId{directoryId, sourceId}, line(line), column(column)
{}
qint64 sourceId;
qint64 line;
qint64 column;
};
struct Source
{
Source(qint64 sourceId, Utils::PathString &&sourcePath)
: sourceId(sourceId), sourcePath(std::move(sourcePath))
{}
qint64 sourceId;
Utils::PathString sourcePath;
};
std::vector<Location> locations;
std::unordered_map<qint64, Utils::PathString> sources;
ClangBackEnd::FilePathId filePathId;
int line;
int column;
};
using SourceLocations = std::vector<SourceLocation>;
} // namespace ClangRefactoring

View File

@@ -27,6 +27,7 @@
#include <utils/smallstring.h>
#include <filepathid.h>
#include <sourcelocations.h>
#include <algorithm>
@@ -39,68 +40,20 @@ class SymbolQuery
using ReadStatement = typename StatementFactory::ReadStatementType;
public:
using Location = SourceLocations::Location;
using Source = SourceLocations::Source;
SymbolQuery(StatementFactory &statementFactory)
: m_statementFactory(statementFactory)
{}
SourceLocations locationsAt(const Utils::PathString &filePath, uint line, uint utf8Column)
SourceLocations locationsAt(ClangBackEnd::FilePathId filePathId, int line, int utf8Column)
{
ReadStatement &locationsStatement = m_statementFactory.selectLocationsForSymbolLocation;
const std::size_t reserveSize = 128;
auto locations = locationsStatement.template values<Location, 3>(
reserveSize,
filePath,
line,
utf8Column);
const std::vector<qint64> sourceIds = uniqueSourceIds(locations);
ReadStatement &sourcesStatement = m_statementFactory.selectSourcePathForId;
auto sources = sourcesStatement.template values<Source, 2>(
reserveSize,
sourceIds);
return {locations, sourcesToHashMap(sources)};
}
static
qint64 sourceId(const Location &location)
{
return location.sourceId;
}
static
std::vector<qint64> uniqueSourceIds(const std::vector<Location> &locations)
{
std::vector<qint64> ids;
ids.reserve(locations.size());
std::transform(locations.begin(),
locations.end(),
std::back_inserter(ids),
sourceId);
auto newEnd = std::unique(ids.begin(), ids.end());
ids.erase(newEnd, ids.end());
return ids;
}
static
std::unordered_map<qint64, Utils::PathString> sourcesToHashMap(const std::vector<Source> &sources)
{
std::unordered_map<qint64, Utils::PathString> dictonary;
for (const Source &source : sources)
dictonary.emplace(source.sourceId, std::move(source.sourcePath));
return dictonary;
return locationsStatement.template values<SourceLocation, 4>(reserveSize,
filePathId.fileNameId,
line,
utf8Column);
}
private: