Clang: Reduce database accesses

If we prefetch data from the database to the caches we reduce the database
transaction calls which are quite expensive.

Change-Id: I617a0d886807402e0a94291a913a77f989970b55
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2019-08-20 14:45:01 +02:00
parent 04f8ff6404
commit c174eb378a
47 changed files with 617 additions and 213 deletions

View File

@@ -27,6 +27,7 @@
#include "clangsupport_global.h" #include "clangsupport_global.h"
#include "filepath.h" #include "filepath.h"
#include "filepathid.h"
#include <vector> #include <vector>
@@ -39,13 +40,15 @@ public:
FileContainer() = default; FileContainer() = default;
FileContainer(FilePath &&filePath, FileContainer(FilePath &&filePath,
FilePathId filePathId,
Utils::SmallString &&unsavedFileContent, Utils::SmallString &&unsavedFileContent,
Utils::SmallStringVector &&commandLineArguments = {}, Utils::SmallStringVector &&commandLineArguments = {},
quint32 documentRevision = 0) quint32 documentRevision = 0)
: filePath(std::move(filePath)), : filePath(std::move(filePath))
unsavedFileContent(std::move(unsavedFileContent)), , filePathId(filePathId)
commandLineArguments(std::move(commandLineArguments)), , unsavedFileContent(std::move(unsavedFileContent))
documentRevision(documentRevision) , commandLineArguments(std::move(commandLineArguments))
, documentRevision(documentRevision)
{ {
} }
@@ -81,16 +84,11 @@ public:
< std::tie(second.filePath, second.documentRevision, second.unsavedFileContent, second.commandLineArguments); < std::tie(second.filePath, second.documentRevision, second.unsavedFileContent, second.commandLineArguments);
} }
FileContainer clone() const FileContainer clone() const { return *this; }
{
return FileContainer(filePath.clone(),
unsavedFileContent.clone(),
commandLineArguments.clone(),
documentRevision);
}
public: public:
FilePath filePath; FilePath filePath;
FilePathId filePathId;
Utils::SmallString unsavedFileContent; Utils::SmallString unsavedFileContent;
Utils::SmallStringVector commandLineArguments; Utils::SmallStringVector commandLineArguments;
quint32 documentRevision = 0; quint32 documentRevision = 0;

View File

@@ -67,13 +67,20 @@ public:
FilePathCache(FilePathStorage &filePathStorage) FilePathCache(FilePathStorage &filePathStorage)
: m_filePathStorage(filePathStorage) : m_filePathStorage(filePathStorage)
{ {
m_directoryPathCache.populate(filePathStorage.fetchAllDirectories()); populateIfEmpty();
m_fileNameCache.populate(filePathStorage.fetchAllSources());
} }
FilePathCache(FilePathCache &&) = default; FilePathCache(FilePathCache &&) = default;
FilePathCache &operator=(FilePathCache &&) = default; FilePathCache &operator=(FilePathCache &&) = default;
void populateIfEmpty()
{
if (m_fileNameCache.isEmpty()) {
m_directoryPathCache.populate(m_filePathStorage.fetchAllDirectories());
m_fileNameCache.populate(m_filePathStorage.fetchAllSources());
}
}
template<typename Cache> template<typename Cache>
Cache clone() Cache clone()
{ {
@@ -126,8 +133,7 @@ public:
return FileNameEntry{entry.sourceName, entry.directoryId}; return FileNameEntry{entry.sourceName, entry.directoryId};
}; };
FileNameEntry entry = m_fileNameCache.string(filePathId.filePathId, auto entry = m_fileNameCache.string(filePathId.filePathId, fetchSoureNameAndDirectoryId);
fetchSoureNameAndDirectoryId);
auto fetchDirectoryPath = [&] (int id) { return m_filePathStorage.fetchDirectoryPath(id); }; auto fetchDirectoryPath = [&] (int id) { return m_filePathStorage.fetchDirectoryPath(id); };
@@ -157,9 +163,6 @@ public:
return FileNameEntry{entry.sourceName, entry.directoryId}; return FileNameEntry{entry.sourceName, entry.directoryId};
}; };
FileNameEntry entry = m_fileNameCache.string(filePathId.filePathId,
fetchSoureNameAndDirectoryId);
return m_fileNameCache.string(filePathId.filePathId, fetchSoureNameAndDirectoryId).directoryId; return m_fileNameCache.string(filePathId.filePathId, fetchSoureNameAndDirectoryId).directoryId;
} }

View File

@@ -57,6 +57,11 @@ void FilePathCaching::addFilePaths(const FilePaths &filePaths)
m_cache.addFilePaths(filePaths); m_cache.addFilePaths(filePaths);
} }
void FilePathCaching::populateIfEmpty()
{
m_cache.populateIfEmpty();
}
FilePathId CopyableFilePathCaching::filePathId(FilePathView filePath) const FilePathId CopyableFilePathCaching::filePathId(FilePathView filePath) const
{ {
return m_cache.filePathId(filePath); return m_cache.filePathId(filePath);
@@ -87,4 +92,9 @@ void CopyableFilePathCaching::addFilePaths(const FilePaths &filePaths)
m_cache.addFilePaths(filePaths); m_cache.addFilePaths(filePaths);
} }
void CopyableFilePathCaching::populateIfEmpty()
{
m_cache.populateIfEmpty();
}
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -56,6 +56,7 @@ public:
Utils::PathString directoryPath(DirectoryPathId directoryPathId) const override; Utils::PathString directoryPath(DirectoryPathId directoryPathId) const override;
DirectoryPathId directoryPathId(FilePathId filePathId) const override; DirectoryPathId directoryPathId(FilePathId filePathId) const override;
void addFilePaths(const ClangBackEnd::FilePaths &filePaths) override; void addFilePaths(const ClangBackEnd::FilePaths &filePaths) override;
void populateIfEmpty() override;
private: private:
Factory m_factory; Factory m_factory;
@@ -80,6 +81,7 @@ public:
Utils::PathString directoryPath(DirectoryPathId directoryPathId) const override; Utils::PathString directoryPath(DirectoryPathId directoryPathId) const override;
DirectoryPathId directoryPathId(FilePathId filePathId) const override; DirectoryPathId directoryPathId(FilePathId filePathId) const override;
void addFilePaths(const ClangBackEnd::FilePaths &filePaths) override; void addFilePaths(const ClangBackEnd::FilePaths &filePaths) override;
void populateIfEmpty() override;
private: private:
Cache m_cache; Cache m_cache;

View File

@@ -45,6 +45,7 @@ public:
virtual DirectoryPathId directoryPathId(FilePathId filePathId) const = 0; virtual DirectoryPathId directoryPathId(FilePathId filePathId) const = 0;
virtual Utils::PathString directoryPath(DirectoryPathId directoryPathId) const = 0; virtual Utils::PathString directoryPath(DirectoryPathId directoryPathId) const = 0;
virtual void addFilePaths(const ClangBackEnd::FilePaths &filePaths) = 0; virtual void addFilePaths(const ClangBackEnd::FilePaths &filePaths) = 0;
virtual void populateIfEmpty() = 0;
template<typename Container> template<typename Container>
FilePathIds filePathIds(Container &&filePaths) const FilePathIds filePathIds(Container &&filePaths) const

View File

@@ -53,7 +53,7 @@ void GeneratedFiles::update(const V2::FileContainers &fileContainers)
V2::FileContainers unionFileContainers; V2::FileContainers unionFileContainers;
unionFileContainers.reserve(m_fileContainers.size() + fileContainers.size()); unionFileContainers.reserve(m_fileContainers.size() + fileContainers.size());
auto compare = [] (const V2::FileContainer &first, const V2::FileContainer &second) { auto compare = [](const V2::FileContainer &first, const V2::FileContainer &second) {
return first.filePath < second.filePath; return first.filePath < second.filePath;
}; };
@@ -69,10 +69,7 @@ void GeneratedFiles::update(const V2::FileContainers &fileContainers)
class Compare { class Compare {
public: public:
bool operator()(const FilePath &first, const FilePath &second) bool operator()(const FilePath &first, const FilePath &second) { return first < second; }
{
return first < second;
}
bool operator()(const V2::FileContainer &first, const V2::FileContainer &second) bool operator()(const V2::FileContainer &first, const V2::FileContainer &second)
{ {
return first.filePath < second.filePath; return first.filePath < second.filePath;
@@ -116,4 +113,16 @@ const V2::FileContainers &GeneratedFiles::fileContainers() const
return m_fileContainers; return m_fileContainers;
} }
FilePathIds GeneratedFiles::filePathIds() const
{
auto ids = Utils::transform<FilePathIds>(m_fileContainers,
[](const V2::FileContainer &fileContainer) {
return fileContainer.filePathId;
});
std::sort(ids.begin(), ids.end());
return ids;
}
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -38,6 +38,7 @@ public:
bool isValid() const; bool isValid() const;
const V2::FileContainers &fileContainers() const; const V2::FileContainers &fileContainers() const;
FilePathIds filePathIds() const;
private: private:
V2::FileContainers m_fileContainers; V2::FileContainers m_fileContainers;

View File

@@ -38,6 +38,7 @@ public:
virtual bool isValid() const = 0; virtual bool isValid() const = 0;
virtual const V2::FileContainers &fileContainers() const = 0; virtual const V2::FileContainers &fileContainers() const = 0;
virtual FilePathIds filePathIds() const = 0;
protected: protected:
~GeneratedFilesInterface() = default; ~GeneratedFilesInterface() = default;

View File

@@ -109,26 +109,33 @@ public:
} }
} }
ProjectPartId fetchProjectPartIdUnguarded(Utils::SmallStringView projectPartName) const override
{
auto optionalProjectPartId = fetchProjectPartIdStatement.template value<ProjectPartId>(
projectPartName);
if (optionalProjectPartId) {
return *optionalProjectPartId;
} else {
insertProjectPartNameStatement.write(projectPartName);
return static_cast<int>(database.lastInsertedRowId());
}
return {};
}
ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) const override ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) const override
{ {
try { try {
Sqlite::DeferredTransaction transaction{database}; Sqlite::DeferredTransaction transaction{database};
ProjectPartId projectPartId; ProjectPartId projectPartId = fetchProjectPartIdUnguarded(projectPartName);
auto optionalProjectPartId = fetchProjectPartIdStatement.template value<ProjectPartId>(
projectPartName);
if (optionalProjectPartId) {
projectPartId = *optionalProjectPartId;
} else {
insertProjectPartNameStatement.write(projectPartName);
projectPartId = static_cast<int>(database.lastInsertedRowId());
}
transaction.commit(); transaction.commit();
return projectPartId; return projectPartId;
} catch (const Sqlite::StatementIsBusy &) { } catch (const Sqlite::StatementIsBusy &) {
return fetchProjectPartId(projectPartName); return fetchProjectPartId(projectPartName);
} }
@@ -330,6 +337,23 @@ public:
Utils::SmallString::number(projectPartId.projectPathId)); Utils::SmallString::number(projectPartId.projectPathId));
} }
Internal::ProjectPartNameIds fetchAllProjectPartNamesAndIds() const
{
try {
Sqlite::DeferredTransaction transaction{database};
ReadStatement &statement = fetchAllProjectPartNamesAndIdsStatement;
auto values = statement.template values<Internal::ProjectPartNameId, 2>(256);
transaction.commit();
return values;
} catch (const Sqlite::StatementIsBusy &) {
return fetchAllProjectPartNamesAndIds();
}
}
public: public:
Sqlite::ImmediateNonThrowingDestructorTransaction transaction; Sqlite::ImmediateNonThrowingDestructorTransaction transaction;
Database &database; Database &database;
@@ -383,5 +407,7 @@ public:
"SELECT projectPchBuildTime FROM precompiledHeaders WHERE projectPartId = ?", database}; "SELECT projectPchBuildTime FROM precompiledHeaders WHERE projectPartId = ?", database};
WriteStatement resetDependentIndexingTimeStampsStatement{ WriteStatement resetDependentIndexingTimeStampsStatement{
"UPDATE fileStatuses SET indexingTimeStamp = NULL WHERE sourceId = ?", database}; "UPDATE fileStatuses SET indexingTimeStamp = NULL WHERE sourceId = ?", database};
mutable ReadStatement fetchAllProjectPartNamesAndIdsStatement{
"SELECT projectPartName, projectPartId FROM projectParts", database};
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -25,7 +25,8 @@
#pragma once #pragma once
#include <projectpartcontainer.h> #include "projectpartcontainer.h"
#include "projectpartstoragestructs.h"
#include <sqlitetransaction.h> #include <sqlitetransaction.h>
#include <utils/optional.h> #include <utils/optional.h>
@@ -46,8 +47,10 @@ public:
virtual ProjectPartContainers fetchProjectParts() const = 0; virtual ProjectPartContainers fetchProjectParts() const = 0;
virtual ProjectPartContainers fetchProjectParts(const ProjectPartIds &projectPartIds) const = 0; virtual ProjectPartContainers fetchProjectParts(const ProjectPartIds &projectPartIds) const = 0;
virtual ProjectPartId fetchProjectPartIdUnguarded(Utils::SmallStringView projectPartName) const = 0;
virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) const = 0; virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) const = 0;
virtual Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const = 0; virtual Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const = 0;
virtual Internal::ProjectPartNameIds fetchAllProjectPartNamesAndIds() const = 0;
virtual void updateProjectPart(ProjectPartId projectPartId, virtual void updateProjectPart(ProjectPartId projectPartId,
const Utils::SmallStringVector &commandLineArguments, const Utils::SmallStringVector &commandLineArguments,
const CompilerMacros &compilerMacros, const CompilerMacros &compilerMacros,

View File

@@ -46,8 +46,11 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/namevalueitem.h> #include <utils/namevalueitem.h>
#include <QDirIterator>
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <iostream>
namespace ClangPchManager { namespace ClangPchManager {
@@ -68,6 +71,7 @@ void ProjectUpdater::updateProjectParts(const std::vector<CppTools::ProjectPart
Utils::SmallStringVector &&toolChainArguments) Utils::SmallStringVector &&toolChainArguments)
{ {
addProjectFilesToFilePathCache(projectParts); addProjectFilesToFilePathCache(projectParts);
fetchProjectPartIds(projectParts);
m_server.updateProjectParts( m_server.updateProjectParts(
ClangBackEnd::UpdateProjectPartsMessage{toProjectPartContainers(projectParts), ClangBackEnd::UpdateProjectPartsMessage{toProjectPartContainers(projectParts),
@@ -237,7 +241,7 @@ void updateWithSettings(ClangBackEnd::CompilerMacros &macros,
} // namespace } // namespace
ClangBackEnd::CompilerMacros ProjectUpdater::createCompilerMacros( ClangBackEnd::CompilerMacros ProjectUpdater::createCompilerMacros(
const ProjectExplorer::Macros &projectMacros, Utils::NameValueItems &&settingsMacros) const const ProjectExplorer::Macros &projectMacros, Utils::NameValueItems &&settingsMacros)
{ {
int index = 0; int index = 0;
auto macros = Utils::transform<ClangBackEnd::CompilerMacros>( auto macros = Utils::transform<ClangBackEnd::CompilerMacros>(
@@ -347,10 +351,10 @@ ClangBackEnd::ProjectPartContainer ProjectUpdater::toProjectPartContainer(
auto includeSearchPaths = createIncludeSearchPaths(*projectPart); auto includeSearchPaths = createIncludeSearchPaths(*projectPart);
const QByteArray projectPartName = projectPart->id().toUtf8(); ClangBackEnd::ProjectPartId projectPartId = m_projectPartIdCache.stringId(
Utils::PathString{projectPart->id()}, [&](Utils::SmallStringView projectPartName) {
ClangBackEnd::ProjectPartId projectPartId = m_projectPartsStorage.fetchProjectPartId( return m_projectPartsStorage.fetchProjectPartId(projectPartName);
projectPartName); });
ClangIndexingProjectSettings *settings = m_settingsManager.settings(projectPart->project); ClangIndexingProjectSettings *settings = m_settingsManager.settings(projectPart->project);
@@ -415,36 +419,31 @@ ClangBackEnd::FilePaths ProjectUpdater::createExcludedPaths(
QString ProjectUpdater::fetchProjectPartName(ClangBackEnd::ProjectPartId projectPartId) const QString ProjectUpdater::fetchProjectPartName(ClangBackEnd::ProjectPartId projectPartId) const
{ {
return m_projectPartsStorage.fetchProjectPartName(projectPartId).toQString(); return QString(m_projectPartIdCache.string(projectPartId.projectPathId,
[&](ClangBackEnd::ProjectPartId projectPartId) {
return m_projectPartsStorage.fetchProjectPartName(
projectPartId);
}));
} }
ClangBackEnd::ProjectPartIds ProjectUpdater::toProjectPartIds( ClangBackEnd::ProjectPartIds ProjectUpdater::toProjectPartIds(
const QStringList &projectPartNames) const const QStringList &projectPartNamesAsQString) const
{ {
ClangBackEnd::ProjectPartIds projectPartIds; ClangBackEnd::ProjectPartIds projectPartIds;
projectPartIds.reserve(projectPartIds.size()); projectPartIds.reserve(projectPartIds.size());
std::transform(projectPartNames.begin(), auto projectPartNames = Utils::transform<std::vector<Utils::PathString>>(
projectPartNames.end(), projectPartNamesAsQString, [&](const QString &projectPartName) { return projectPartName; });
std::back_inserter(projectPartIds),
[&](const QString &projectPartName) {
return m_projectPartsStorage.fetchProjectPartId(
Utils::SmallString{projectPartName});
});
return projectPartIds; return m_projectPartIdCache.stringIds(projectPartNames, [&](Utils::SmallStringView projectPartName) {
return m_projectPartsStorage.fetchProjectPartId(projectPartName);
});
} }
void ProjectUpdater::addProjectFilesToFilePathCache(const std::vector<CppTools::ProjectPart *> &projectParts) void ProjectUpdater::addProjectFilesToFilePathCache(const std::vector<CppTools::ProjectPart *> &projectParts)
{ {
std::size_t fileCount = std::accumulate(projectParts.begin(),
projectParts.end(),
std::size_t(0),
[](std::size_t value, CppTools::ProjectPart *projectPart) {
return value + std::size_t(projectPart->files.size());
});
ClangBackEnd::FilePaths filePaths; ClangBackEnd::FilePaths filePaths;
filePaths.reserve(fileCount); filePaths.reserve(10000);
for (CppTools::ProjectPart *projectPart : projectParts) { for (CppTools::ProjectPart *projectPart : projectParts) {
for (const CppTools::ProjectFile &file : projectPart->files) for (const CppTools::ProjectFile &file : projectPart->files)
@@ -455,4 +454,28 @@ void ProjectUpdater::addProjectFilesToFilePathCache(const std::vector<CppTools::
m_filePathCache.addFilePaths(filePaths); m_filePathCache.addFilePaths(filePaths);
} }
void ProjectUpdater::fetchProjectPartIds(const std::vector<CppTools::ProjectPart *> &projectParts)
{
std::unique_ptr<Sqlite::DeferredTransaction> transaction;
auto projectPartNames = Utils::transform<std::vector<Utils::PathString>>(
projectParts, [](CppTools::ProjectPart *projectPart) { return projectPart->id(); });
auto projectPartNameViews = Utils::transform<std::vector<Utils::SmallStringView>>(
projectPartNames,
[](const Utils::PathString &projectPartName) { return projectPartName.toStringView(); });
m_projectPartIdCache
.addStrings(std::move(projectPartNameViews), [&](Utils::SmallStringView projectPartName) {
if (!transaction)
transaction = std::make_unique<Sqlite::DeferredTransaction>(
m_projectPartsStorage.transactionBackend());
return m_projectPartsStorage.fetchProjectPartIdUnguarded(projectPartName);
});
if (transaction)
transaction->commit();
} // namespace ClangPchManager
} // namespace ClangPchManager } // namespace ClangPchManager

View File

@@ -34,6 +34,8 @@
#include <includesearchpath.h> #include <includesearchpath.h>
#include <projectpartcontainer.h> #include <projectpartcontainer.h>
#include <projectpartsstorageinterface.h> #include <projectpartsstorageinterface.h>
#include <projectpartstoragestructs.h>
#include <stringcache.h>
#include <projectexplorer/headerpath.h> #include <projectexplorer/headerpath.h>
@@ -66,6 +68,14 @@ class ClangIndexingProjectSettings;
class CLANGPCHMANAGER_EXPORT ProjectUpdater class CLANGPCHMANAGER_EXPORT ProjectUpdater
{ {
using StringCache = ClangBackEnd::StringCache<Utils::PathString,
Utils::SmallStringView,
ClangBackEnd::ProjectPartId,
ClangBackEnd::NonLockingMutex,
decltype(&Utils::reverseCompare),
Utils::reverseCompare,
ClangBackEnd::Internal::ProjectPartNameId>;
public: public:
struct SystemAndProjectIncludeSearchPaths struct SystemAndProjectIncludeSearchPaths
{ {
@@ -77,11 +87,13 @@ public:
ClangBackEnd::FilePathCachingInterface &filePathCache, ClangBackEnd::FilePathCachingInterface &filePathCache,
ClangBackEnd::ProjectPartsStorageInterface &projectPartsStorage, ClangBackEnd::ProjectPartsStorageInterface &projectPartsStorage,
ClangIndexingSettingsManager &settingsManager) ClangIndexingSettingsManager &settingsManager)
: m_server(server) : m_filePathCache(filePathCache)
, m_filePathCache(filePathCache) , m_server(server)
, m_projectPartsStorage(projectPartsStorage) , m_projectPartsStorage(projectPartsStorage)
, m_settingsManager(settingsManager) , m_settingsManager(settingsManager)
{} {
m_projectPartIdCache.populate(m_projectPartsStorage.fetchAllProjectPartNamesAndIds());
}
void updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts, void updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts,
Utils::SmallStringVector &&toolChainArguments); Utils::SmallStringVector &&toolChainArguments);
@@ -104,8 +116,8 @@ public:
void addToHeaderAndSources(HeaderAndSources &headerAndSources, void addToHeaderAndSources(HeaderAndSources &headerAndSources,
const CppTools::ProjectFile &projectFile) const; const CppTools::ProjectFile &projectFile) const;
static QStringList toolChainArguments(CppTools::ProjectPart *projectPart); static QStringList toolChainArguments(CppTools::ProjectPart *projectPart);
ClangBackEnd::CompilerMacros createCompilerMacros(const ProjectExplorer::Macros &projectMacros, static ClangBackEnd::CompilerMacros createCompilerMacros(const ProjectExplorer::Macros &projectMacros,
Utils::NameValueItems &&settingsMacros) const; Utils::NameValueItems &&settingsMacros);
static SystemAndProjectIncludeSearchPaths createIncludeSearchPaths( static SystemAndProjectIncludeSearchPaths createIncludeSearchPaths(
const CppTools::ProjectPart &projectPart); const CppTools::ProjectPart &projectPart);
static ClangBackEnd::FilePaths createExcludedPaths( static ClangBackEnd::FilePaths createExcludedPaths(
@@ -115,16 +127,19 @@ public:
ClangBackEnd::ProjectPartIds toProjectPartIds(const QStringList &projectPartNames) const; ClangBackEnd::ProjectPartIds toProjectPartIds(const QStringList &projectPartNames) const;
private:
void addProjectFilesToFilePathCache(const std::vector<CppTools::ProjectPart *> &projectParts); void addProjectFilesToFilePathCache(const std::vector<CppTools::ProjectPart *> &projectParts);
void fetchProjectPartIds(const std::vector<CppTools::ProjectPart *> &projectParts);
protected:
ClangBackEnd::FilePathCachingInterface &m_filePathCache;
private: private:
ClangBackEnd::GeneratedFiles m_generatedFiles; ClangBackEnd::GeneratedFiles m_generatedFiles;
ClangBackEnd::FilePaths m_excludedPaths; ClangBackEnd::FilePaths m_excludedPaths;
ClangBackEnd::ProjectManagementServerInterface &m_server; ClangBackEnd::ProjectManagementServerInterface &m_server;
ClangBackEnd::FilePathCachingInterface &m_filePathCache;
ClangBackEnd::ProjectPartsStorageInterface &m_projectPartsStorage; ClangBackEnd::ProjectPartsStorageInterface &m_projectPartsStorage;
ClangIndexingSettingsManager &m_settingsManager; ClangIndexingSettingsManager &m_settingsManager;
mutable StringCache m_projectPartIdCache;
}; };
} // namespace ClangPchManager } // namespace ClangPchManager

View File

@@ -29,6 +29,8 @@
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <filepathcachinginterface.h>
namespace ClangPchManager { namespace ClangPchManager {
namespace Internal { namespace Internal {
@@ -38,16 +40,21 @@ CppTools::CppModelManager *cppModelManager()
return CppTools::CppModelManager::instance(); return CppTools::CppModelManager::instance();
} }
std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles() std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles(
ClangBackEnd::FilePathCachingInterface &filePathCache)
{ {
auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports(); auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports();
std::vector<ClangBackEnd::V2::FileContainer> generatedFiles; std::vector<ClangBackEnd::V2::FileContainer> generatedFiles;
generatedFiles.reserve(std::size_t(abstractEditors.size())); generatedFiles.reserve(std::size_t(abstractEditors.size()));
auto toFileContainer = [] (const CppTools::AbstractEditorSupport *abstractEditor) { auto toFileContainer = [&](const CppTools::AbstractEditorSupport *abstractEditor) {
return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()), ClangBackEnd::FilePath filePath(abstractEditor->fileName());
Utils::SmallString::fromQByteArray(abstractEditor->contents()), ClangBackEnd::FilePathId filePathId = filePathCache.filePathId(filePath);
{}); return ClangBackEnd::V2::FileContainer(std::move(filePath),
filePathId,
Utils::SmallString::fromQByteArray(
abstractEditor->contents()),
{});
}; };
std::transform(abstractEditors.begin(), std::transform(abstractEditors.begin(),

View File

@@ -32,6 +32,8 @@
#include <filecontainerv2.h> #include <filecontainerv2.h>
#include <utils/algorithm.h>
#include <QObject> #include <QObject>
namespace ProjectExplorer { namespace ProjectExplorer {
@@ -46,7 +48,8 @@ namespace ClangPchManager {
namespace Internal { namespace Internal {
CLANGPCHMANAGER_EXPORT CppTools::CppModelManager *cppModelManager(); CLANGPCHMANAGER_EXPORT CppTools::CppModelManager *cppModelManager();
CLANGPCHMANAGER_EXPORT std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles(); CLANGPCHMANAGER_EXPORT std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles(
ClangBackEnd::FilePathCachingInterface &filePathCache);
CLANGPCHMANAGER_EXPORT std::vector<CppTools::ProjectPart*> createProjectParts(ProjectExplorer::Project *project); CLANGPCHMANAGER_EXPORT std::vector<CppTools::ProjectPart*> createProjectParts(ProjectExplorer::Project *project);
} }
@@ -83,9 +86,13 @@ public:
ProjectUpdaterType::removeProjectParts(projectPartIds); ProjectUpdaterType::removeProjectParts(projectPartIds);
} }
void abstractEditorUpdated(const QString &filePath, const QByteArray &contents) void abstractEditorUpdated(const QString &qFilePath, const QByteArray &contents)
{ {
ProjectUpdaterType::updateGeneratedFiles({{ClangBackEnd::FilePath{filePath}, contents}}); ClangBackEnd::FilePath filePath{qFilePath};
ClangBackEnd::FilePathId filePathId = ProjectUpdaterType::m_filePathCache.filePathId(
filePath);
ProjectUpdaterType::updateGeneratedFiles({{std::move(filePath), filePathId, contents}});
} }
void abstractEditorRemoved(const QString &filePath) void abstractEditorRemoved(const QString &filePath)
@@ -98,6 +105,14 @@ protected:
const Utils::FilePath &, const Utils::FilePath &,
const Utils::FilePathList &targets) override const Utils::FilePathList &targets) override
{ {
auto filePaths = Utils::transform<ClangBackEnd::FilePaths>(targets,
[](const Utils::FilePath &filePath) {
return ClangBackEnd::FilePath{
filePath.toString()};
});
ProjectUpdater::m_filePathCache.addFilePaths(filePaths);
for (const Utils::FilePath &target : targets) for (const Utils::FilePath &target : targets)
abstractEditorUpdated(target.toString(), {}); abstractEditorUpdated(target.toString(), {});
} }
@@ -105,7 +120,8 @@ protected:
private: private:
void connectToCppModelManager() void connectToCppModelManager()
{ {
ProjectUpdaterType::updateGeneratedFiles(Internal::createGeneratedFiles()); ProjectUpdaterType::updateGeneratedFiles(
Internal::createGeneratedFiles(ProjectUpdaterType::m_filePathCache));
QObject::connect(Internal::cppModelManager(), QObject::connect(Internal::cppModelManager(),
&CppTools::CppModelManager::projectPartsUpdated, &CppTools::CppModelManager::projectPartsUpdated,

View File

@@ -82,10 +82,9 @@ void ClangQueryProjectsFindFilter::requestSourceRangesAndDiagnostics(const QStri
{ {
const QString filePath = temporaryFile.fileName(); const QString filePath = temporaryFile.fileName();
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message(queryText, ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message(
{ClangBackEnd::FilePath(filePath), queryText,
exampleContent, {ClangBackEnd::FilePath(filePath), 1, exampleContent, {"cc", "-std=c++1z", toNative(filePath)}});
{"cc", "-std=c++1z", toNative(filePath)}});
m_server.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message)); m_server.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message));
} }
@@ -204,10 +203,9 @@ void appendSource(std::vector<ClangBackEnd::V2::FileContainer> &sources,
if (!unsavedContentContains(sourceFilePath, unsavedContent) && !isCHeader(projectFile.kind)) { if (!unsavedContentContains(sourceFilePath, unsavedContent) && !isCHeader(projectFile.kind)) {
sources.emplace_back(ClangBackEnd::FilePath(projectFile.path), sources.emplace_back(ClangBackEnd::FilePath(projectFile.path),
-1,
"", "",
createCommandLine(projectPart.data(), createCommandLine(projectPart.data(), projectFile.path, projectFile.kind));
projectFile.path,
projectFile.kind));
} }
} }

View File

@@ -108,10 +108,12 @@ std::vector<ClangBackEnd::V2::FileContainer> createUnsavedContents()
std::vector<ClangBackEnd::V2::FileContainer> unsavedContents; std::vector<ClangBackEnd::V2::FileContainer> unsavedContents;
unsavedContents.reserve(std::size_t(abstractEditors.size())); unsavedContents.reserve(std::size_t(abstractEditors.size()));
auto toFileContainer = [] (const CppTools::AbstractEditorSupport *abstractEditor) { auto toFileContainer = [](const CppTools::AbstractEditorSupport *abstractEditor) {
return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()), return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()),
Utils::SmallString::fromQByteArray(abstractEditor->contents()), -1,
{}); Utils::SmallString::fromQByteArray(
abstractEditor->contents()),
{});
}; };
std::transform(abstractEditors.begin(), std::transform(abstractEditors.begin(),

View File

@@ -37,16 +37,21 @@ CppTools::CppModelManager *cppModelManager()
return CppTools::CppModelManager::instance(); return CppTools::CppModelManager::instance();
} }
std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles() std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles(
ClangBackEnd::FilePathCachingInterface &filePathCache)
{ {
auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports(); auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports();
std::vector<ClangBackEnd::V2::FileContainer> generatedFiles; std::vector<ClangBackEnd::V2::FileContainer> generatedFiles;
generatedFiles.reserve(std::size_t(abstractEditors.size())); generatedFiles.reserve(std::size_t(abstractEditors.size()));
auto toFileContainer = [] (const CppTools::AbstractEditorSupport *abstractEditor) { auto toFileContainer = [&](const CppTools::AbstractEditorSupport *abstractEditor) {
return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()), ClangBackEnd::FilePath filePath{abstractEditor->fileName()};
Utils::SmallString::fromQByteArray(abstractEditor->contents()), ClangBackEnd::FilePathId filePathId = filePathCache.filePathId(filePath);
{}); return ClangBackEnd::V2::FileContainer(std::move(filePath),
filePathId,
Utils::SmallString::fromQByteArray(
abstractEditor->contents()),
{});
}; };
std::transform(abstractEditors.begin(), std::transform(abstractEditors.begin(),
@@ -76,9 +81,12 @@ QtCreatorRefactoringProjectUpdater::QtCreatorRefactoringProjectUpdater(
connectToCppModelManager(); connectToCppModelManager();
} }
void QtCreatorRefactoringProjectUpdater::abstractEditorUpdated(const QString &filePath, const QByteArray &contents) void QtCreatorRefactoringProjectUpdater::abstractEditorUpdated(const QString &qFilePath,
const QByteArray &contents)
{ {
RefactoringProjectUpdater::updateGeneratedFiles({{ClangBackEnd::FilePath{filePath}, contents}}); ClangBackEnd::FilePath filePath{qFilePath};
ClangBackEnd::FilePathId filePathId = m_filePathCache.filePathId(filePath);
RefactoringProjectUpdater::updateGeneratedFiles({{std::move(filePath), filePathId, contents}});
} }
void QtCreatorRefactoringProjectUpdater::abstractEditorRemoved(const QString &filePath) void QtCreatorRefactoringProjectUpdater::abstractEditorRemoved(const QString &filePath)
@@ -88,7 +96,7 @@ void QtCreatorRefactoringProjectUpdater::abstractEditorRemoved(const QString &fi
void QtCreatorRefactoringProjectUpdater::connectToCppModelManager() void QtCreatorRefactoringProjectUpdater::connectToCppModelManager()
{ {
RefactoringProjectUpdater::updateGeneratedFiles(createGeneratedFiles()); RefactoringProjectUpdater::updateGeneratedFiles(createGeneratedFiles(m_filePathCache));
QObject::connect(cppModelManager(), QObject::connect(cppModelManager(),
&CppTools::CppModelManager::abstractEditorSupportContentsUpdated, &CppTools::CppModelManager::abstractEditorSupportContentsUpdated,

View File

@@ -232,9 +232,8 @@ struct Data // because we have a cycle dependency
pchTaskGenerator, pchTaskGenerator,
projectParts, projectParts,
generatedFiles, generatedFiles,
buildDependencyStorage/*, buildDependencyStorage,
buildDependencyProvider, filePathCache};
filePathCache*/};
TaskScheduler systemTaskScheduler{pchCreatorManager, TaskScheduler systemTaskScheduler{pchCreatorManager,
pchTaskQueue, pchTaskQueue,
pchCreationProgressCounter, pchCreationProgressCounter,

View File

@@ -41,6 +41,7 @@
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <QApplication> #include <QApplication>
#include <QDirIterator>
#include <algorithm> #include <algorithm>
@@ -50,12 +51,14 @@ PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
PchTaskGeneratorInterface &pchTaskGenerator, PchTaskGeneratorInterface &pchTaskGenerator,
ProjectPartsManagerInterface &projectParts, ProjectPartsManagerInterface &projectParts,
GeneratedFilesInterface &generatedFiles, GeneratedFilesInterface &generatedFiles,
BuildDependenciesStorageInterface &buildDependenciesStorage) BuildDependenciesStorageInterface &buildDependenciesStorage,
FilePathCachingInterface &filePathCache)
: m_fileSystemWatcher(fileSystemWatcher) : m_fileSystemWatcher(fileSystemWatcher)
, m_pchTaskGenerator(pchTaskGenerator) , m_pchTaskGenerator(pchTaskGenerator)
, m_projectPartsManager(projectParts) , m_projectPartsManager(projectParts)
, m_generatedFiles(generatedFiles) , m_generatedFiles(generatedFiles)
, m_buildDependenciesStorage(buildDependenciesStorage) , m_buildDependenciesStorage(buildDependenciesStorage)
, m_filePathCache(filePathCache)
{ {
m_fileSystemWatcher.setNotifier(this); m_fileSystemWatcher.setNotifier(this);
} }
@@ -73,10 +76,43 @@ ProjectPartIds toProjectPartIds(const ProjectPartContainers &projectParts)
}); });
} }
FilePaths gatherPathsInIncludePaths(const ProjectPartContainers &projectParts)
{
FilePaths filePaths;
for (const ProjectPartContainer &projectPart : projectParts) {
for (const IncludeSearchPath &searchPath : projectPart.projectIncludeSearchPaths) {
QDirIterator directoryIterator(QString{searchPath.path},
{"*.h", "*.hpp"},
QDir::Files,
QDirIterator::FollowSymlinks
| QDirIterator::Subdirectories);
while (directoryIterator.hasNext()) {
filePaths.emplace_back(directoryIterator.next());
}
}
for (const IncludeSearchPath &searchPath : projectPart.systemIncludeSearchPaths) {
QDirIterator directoryIterator(QString{searchPath.path},
{"*.h", "*.hpp"},
QDir::Files,
QDirIterator::FollowSymlinks);
while (directoryIterator.hasNext()) {
filePaths.emplace_back(directoryIterator.next());
}
}
}
return filePaths;
}
} // namespace } // namespace
void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message) void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message)
{ {
m_filePathCache.populateIfEmpty();
m_filePathCache.addFilePaths(gatherPathsInIncludePaths(message.projectsParts));
m_toolChainsArgumentsCache.update(message.projectsParts, message.toolChainArguments); m_toolChainsArgumentsCache.update(message.projectsParts, message.toolChainArguments);
auto upToDateProjectParts = m_projectPartsManager.update(message.takeProjectsParts()); auto upToDateProjectParts = m_projectPartsManager.update(message.takeProjectsParts());

View File

@@ -40,6 +40,7 @@ namespace ClangBackEnd {
class SourceRangesAndDiagnosticsForQueryMessage; class SourceRangesAndDiagnosticsForQueryMessage;
class PchTaskGeneratorInterface; class PchTaskGeneratorInterface;
class BuildDependenciesStorageInterface; class BuildDependenciesStorageInterface;
class FilePathCachingInterface;
class PchManagerServer : public PchManagerServerInterface, class PchManagerServer : public PchManagerServerInterface,
public ClangPathWatcherNotifier, public ClangPathWatcherNotifier,
@@ -51,7 +52,8 @@ public:
PchTaskGeneratorInterface &pchTaskGenerator, PchTaskGeneratorInterface &pchTaskGenerator,
ProjectPartsManagerInterface &projectParts, ProjectPartsManagerInterface &projectParts,
GeneratedFilesInterface &generatedFiles, GeneratedFilesInterface &generatedFiles,
BuildDependenciesStorageInterface &buildDependenciesStorage); BuildDependenciesStorageInterface &buildDependenciesStorage,
FilePathCachingInterface &filePathCache);
void end() override; void end() override;
void updateProjectParts(UpdateProjectPartsMessage &&message) override; void updateProjectParts(UpdateProjectPartsMessage &&message) override;
@@ -76,6 +78,7 @@ private:
GeneratedFilesInterface &m_generatedFiles; GeneratedFilesInterface &m_generatedFiles;
BuildDependenciesStorageInterface &m_buildDependenciesStorage; BuildDependenciesStorageInterface &m_buildDependenciesStorage;
ToolChainsArgumentsCache m_toolChainsArgumentsCache; ToolChainsArgumentsCache m_toolChainsArgumentsCache;
FilePathCachingInterface &m_filePathCache;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -56,27 +56,6 @@ namespace {
enum class Change { System, Project, No }; enum class Change { System, Project, No };
Change changedSourceType(const SourceEntries &sources)
{
Change change = Change::No;
for (SourceEntry sourceEntry : sources) {
switch (sourceEntry.sourceType) {
case SourceType::SystemInclude:
case SourceType::TopSystemInclude:
return Change::System;
case SourceType::ProjectInclude:
case SourceType::TopProjectInclude:
change = Change::Project;
break;
case SourceType::Source:
case SourceType::UserInclude:
break;
}
}
return change;
}
Change changedSourceType(SourceEntry sourceEntry, Change oldChange) Change changedSourceType(SourceEntry sourceEntry, Change oldChange)
{ {
switch (sourceEntry.sourceType) { switch (sourceEntry.sourceType) {
@@ -109,16 +88,6 @@ FilePathIds existingSources(const FilePathIds &sources, const FilePathIds &gener
return existingSources; return existingSources;
} }
FilePathIds toFilePathIds(const V2::FileContainers &fileContainers,
FilePathCachingInterface &filePathCache)
{
auto filePaths = Utils::transform<std::vector<FilePathView>>(
fileContainers,
[](const V2::FileContainer &container) { return FilePathView(container.filePath); });
return filePathCache.filePathIds(filePaths);
}
} // namespace } // namespace
ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts) ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts)
@@ -175,7 +144,7 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep
auto systemSplit = updateSystemProjectParts.end(); auto systemSplit = updateSystemProjectParts.end();
FilePathIds generatedFiles = toFilePathIds(m_generatedFiles.fileContainers(), m_filePathCache); FilePathIds generatedFiles = m_generatedFiles.filePathIds();
std::vector<IdPaths> watchedIdPaths; std::vector<IdPaths> watchedIdPaths;
watchedIdPaths.reserve(upToDateProjectParts.size() * 4); watchedIdPaths.reserve(upToDateProjectParts.size() * 4);

View File

@@ -81,6 +81,7 @@ void RefactoringServer::requestSourceRangesForQueryMessage(RequestSourceRangesFo
void RefactoringServer::updateProjectParts(UpdateProjectPartsMessage &&message) void RefactoringServer::updateProjectParts(UpdateProjectPartsMessage &&message)
{ {
m_filePathCache.populateIfEmpty();
m_symbolIndexing.updateProjectParts(message.takeProjectsParts()); m_symbolIndexing.updateProjectParts(message.takeProjectsParts());
} }

View File

@@ -57,7 +57,7 @@ public:
, m_database(database) , m_database(database)
{} {}
void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks) void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks) override
{ {
auto merge = [] (SymbolIndexerTask &&first, SymbolIndexerTask &&second) { auto merge = [] (SymbolIndexerTask &&first, SymbolIndexerTask &&second) {
first.callable = std::move(second.callable); first.callable = std::move(second.callable);
@@ -71,7 +71,7 @@ public:
m_progressCounter.addTotal(int(m_tasks.size() - oldSize)); m_progressCounter.addTotal(int(m_tasks.size() - oldSize));
} }
void removeTasks(const std::vector<int> &projectPartIds) void removeTasks(const ProjectPartIds &projectPartIds) override
{ {
auto shouldBeRemoved = [&] (const SymbolIndexerTask& task) { auto shouldBeRemoved = [&] (const SymbolIndexerTask& task) {
return std::binary_search(projectPartIds.begin(), projectPartIds.end(), task.projectPartId); return std::binary_search(projectPartIds.begin(), projectPartIds.end(), task.projectPartId);
@@ -91,7 +91,7 @@ public:
return m_tasks; return m_tasks;
} }
void processEntries() void processEntries() override
{ {
auto slotUsage = m_symbolIndexerScheduler.slotUsage(); auto slotUsage = m_symbolIndexerScheduler.slotUsage();
uint taskCount = slotUsage.free; uint taskCount = slotUsage.free;

View File

@@ -27,6 +27,8 @@
#include <queueinterface.h> #include <queueinterface.h>
#include <projectpartid.h>
#include <utils/smallstringvector.h> #include <utils/smallstringvector.h>
namespace ClangBackEnd { namespace ClangBackEnd {
@@ -38,8 +40,8 @@ class SymbolIndexerTaskQueueInterface : public QueueInterface
public: public:
virtual void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks) = 0 virtual void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks) = 0
/* [[expects: std::is_sorted(tasks)]] */; /* [[expects: std::is_sorted(tasks)]] */;
virtual void removeTasks(const std::vector<int> &projectPartIds) = 0 virtual void removeTasks(const ProjectPartIds &projectPartIds) = 0
/* [[expects: std::is_sorted(projectPartIds)]] */; /* [[expects: std::is_sorted(projectPartIds)]] */;
protected: protected:
~SymbolIndexerTaskQueueInterface() = default; ~SymbolIndexerTaskQueueInterface() = default;

View File

@@ -106,6 +106,7 @@ protected:
collector.addUnsavedFiles( collector.addUnsavedFiles(
{{{TESTDATA_DIR, "BuildDependencyCollector/project/generated_file.h"}, {{{TESTDATA_DIR, "BuildDependencyCollector/project/generated_file.h"},
id(TESTDATA_DIR "/BuildDependencyCollector/project/generated_file.h"),
"#pragma once", "#pragma once",
{}}}); {}}});
@@ -741,6 +742,7 @@ TEST_F(BuildDependencyCollector, GeneratedFile)
{ {
generatedFiles.update( generatedFiles.update(
{{TESTDATA_DIR "/builddependencycollector/project/generated/generated_file.h", {{TESTDATA_DIR "/builddependencycollector/project/generated/generated_file.h",
id(TESTDATA_DIR "/builddependencycollector/project/generated/generated_file.h"),
"#pragma once"}}); "#pragma once"}});
emptyCollector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/main6.cpp"), emptyCollector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/main6.cpp"),
{"cc", {"cc",
@@ -754,9 +756,9 @@ TEST_F(BuildDependencyCollector, GeneratedFile)
emptyCollector.collect(); emptyCollector.collect();
ASSERT_THAT( ASSERT_THAT(emptyCollector.sourceEntries(),
emptyCollector.sourceEntries(), UnorderedElementsAre(
ElementsAre(HasSource(id(TESTDATA_DIR "/builddependencycollector/project/main6.cpp"), HasSource(id(TESTDATA_DIR "/builddependencycollector/project/main6.cpp"),
SourceType::Source), SourceType::Source),
HasSource(id(TESTDATA_DIR HasSource(id(TESTDATA_DIR
"/builddependencycollector/project/generated/generated_file.h"), "/builddependencycollector/project/generated/generated_file.h"),
@@ -783,8 +785,9 @@ TEST_F(BuildDependencyCollector, Create)
{ {
using ClangBackEnd::IncludeSearchPathType; using ClangBackEnd::IncludeSearchPathType;
ClangBackEnd::BuildDependencyCollector collector{filePathCache, generatedFiles, environment}; ClangBackEnd::BuildDependencyCollector collector{filePathCache, generatedFiles, environment};
generatedFiles.update( generatedFiles.update({{TESTDATA_DIR "/builddependencycollector/project/generated_file.h",
{{TESTDATA_DIR "/builddependencycollector/project/generated_file.h", "#pragma once"}}); id(TESTDATA_DIR "/builddependencycollector/project/generated_file.h"),
"#pragma once"}});
ClangBackEnd::ProjectPartContainer projectPart{ ClangBackEnd::ProjectPartContainer projectPart{
1, 1,
{}, {},

View File

@@ -40,6 +40,7 @@
#include <mutex> #include <mutex>
using ClangBackEnd::ClangQuery; using ClangBackEnd::ClangQuery;
using ClangBackEnd::FilePath;
using ClangBackEnd::FilePathCaching; using ClangBackEnd::FilePathCaching;
using ClangBackEnd::RefactoringDatabaseInitializer; using ClangBackEnd::RefactoringDatabaseInitializer;
@@ -98,7 +99,11 @@ TEST_F(ClangQuerySlowTest, SourceRangeInUnsavedFileDeclarationRange)
"#include \"unsaved.h\"", "#include \"unsaved.h\"",
{"cc", "-std=c++14"}); {"cc", "-std=c++14"});
query.setQuery("functionDecl()"); query.setQuery("functionDecl()");
ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "unsaved.h"}, "void unsaved();", {}}; ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "unsaved.h"},
filePathCache.filePathId(
FilePath{TESTDATA_DIR, "unsaved.h"}),
"void unsaved();",
{}};
query.addUnsavedFiles({unsavedFile}); query.addUnsavedFiles({unsavedFile});
query.findLocations(); query.findLocations();
@@ -125,6 +130,8 @@ TEST_F(ClangQuerySlowTest, DISABLED_SourceRangeInUnsavedFileDeclarationRangeOver
query.addFile({TESTDATA_DIR "/query_simplefunction.cpp"}, "void f() {}", {"cc", "-std=c++14"}); query.addFile({TESTDATA_DIR "/query_simplefunction.cpp"}, "void f() {}", {"cc", "-std=c++14"});
query.setQuery("functionDecl()"); query.setQuery("functionDecl()");
ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR "/query_simplefunction.cpp"}, ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR "/query_simplefunction.cpp"},
filePathCache.filePathId(
FilePath{TESTDATA_DIR, "query_simplefunction.cpp"}),
"void unsaved();", "void unsaved();",
{}}; {}};
query.addUnsavedFiles({unsavedFile}); query.addUnsavedFiles({unsavedFile});

View File

@@ -59,10 +59,10 @@ using testing::SizeIs;
using testing::UnorderedElementsAre; using testing::UnorderedElementsAre;
using testing::_; using testing::_;
using ClangBackEnd::V2::FileContainer; using ClangBackEnd::FilePath;
using ClangBackEnd::SourceRangesContainer;
using ClangBackEnd::SourceRangesForQueryMessage; using ClangBackEnd::SourceRangesForQueryMessage;
using ClangBackEnd::SourceRangesContainer; using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::SourceRangesContainer;
MATCHER_P2(Contains, line, column, MATCHER_P2(Contains, line, column,
std::string(negation ? "isn't " : "is ") std::string(negation ? "isn't " : "is ")
@@ -86,22 +86,20 @@ protected:
ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::FilePathCaching filePathCache{database};
Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"}; Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.cpp"}),
sourceContent.clone(), sourceContent.clone(),
{"cc", {"cc", "-I", TESTDATA_DIR}};
"-I",
TESTDATA_DIR}};
FileContainer source2{{TESTDATA_DIR, "query_simplefunction2.cpp"}, FileContainer source2{{TESTDATA_DIR, "query_simplefunction2.cpp"},
filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction2.cpp"}),
{}, {},
{"cc", {"cc", "-I", TESTDATA_DIR}};
"-I",
TESTDATA_DIR}};
FileContainer source3{{TESTDATA_DIR, "query_simplefunction3.cpp"}, FileContainer source3{{TESTDATA_DIR, "query_simplefunction3.cpp"},
filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction3.cpp"}),
{}, {},
{"cc", {"cc", "-I", TESTDATA_DIR}};
"-I",
TESTDATA_DIR}};
Utils::SmallString unsavedContent{"void f();"}; Utils::SmallString unsavedContent{"void f();"};
FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"}, FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"},
filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.h"}),
unsavedContent.clone(), unsavedContent.clone(),
{}}; {}};
Utils::SmallString query{"functionDecl()"}; Utils::SmallString query{"functionDecl()"};

View File

@@ -122,9 +122,7 @@ protected:
QString unsavedDocumentContent{"void f();"}; QString unsavedDocumentContent{"void f();"};
std::vector<Utils::SmallStringVector> commandLines; std::vector<Utils::SmallStringVector> commandLines;
std::vector<CppTools::ProjectPart::Ptr> projectsParts; std::vector<CppTools::ProjectPart::Ptr> projectsParts;
ClangBackEnd::V2::FileContainer unsavedContent{{"/path/to", "unsaved.cpp"}, ClangBackEnd::V2::FileContainer unsavedContent{{"/path/to", "unsaved.cpp"}, 1, "void f();", {}};
"void f();",
{}};
ProjectExplorer::Project project; ProjectExplorer::Project project;
}; };
@@ -186,17 +184,12 @@ TEST_F(ClangQueryProjectFindFilter, FindAllIsSettingExprectedResultCountInTheRef
TEST_F(ClangQueryProjectFindFilter, FindAllIsCallingRequestSourceRangesAndDiagnosticsForQueryMessage) TEST_F(ClangQueryProjectFindFilter, FindAllIsCallingRequestSourceRangesAndDiagnosticsForQueryMessage)
{ {
ClangBackEnd::RequestSourceRangesForQueryMessage message(findDeclQueryText, ClangBackEnd::RequestSourceRangesForQueryMessage message(
{{{"/path/to", "file1.h"}, findDeclQueryText,
"", {{{"/path/to", "file1.h"}, 1, "", commandLines[0].clone()},
commandLines[0].clone()}, {{"/path/to", "file1.cpp"}, 2, "", commandLines[1].clone()},
{{"/path/to", "file1.cpp"}, {{"/path/to", "file2.cpp"}, 3, "", commandLines[2].clone()}},
"", {unsavedContent.clone()});
commandLines[1].clone()},
{{"/path/to", "file2.cpp"},
"",
commandLines[2].clone()}},
{unsavedContent.clone()});
EXPECT_CALL(mockRefactoringServer, requestSourceRangesForQueryMessage(message)); EXPECT_CALL(mockRefactoringServer, requestSourceRangesForQueryMessage(message));

View File

@@ -79,6 +79,7 @@ protected:
NiceMock<MockFilePathStorage> mockStorage{mockDatabase}; NiceMock<MockFilePathStorage> mockStorage{mockDatabase};
Cache cache{mockStorage}; Cache cache{mockStorage};
NiceMock<MockFilePathStorage> mockStorageFilled{mockDatabase}; NiceMock<MockFilePathStorage> mockStorageFilled{mockDatabase};
Cache cacheNotFilled{mockStorageFilled};
}; };
TEST_F(FilePathCache, FilePathIdWithOutAnyEntryCallDirectoryId) TEST_F(FilePathCache, FilePathIdWithOutAnyEntryCallDirectoryId)
@@ -439,4 +440,51 @@ TEST_F(FilePathCache, UseTransactionIfAddingFilesOnlyInAddFilePathsCalls)
cacheFilled.addFilePaths(FilePathViews{"/path/to/file.h"}); cacheFilled.addFilePaths(FilePathViews{"/path/to/file.h"});
} }
TEST_F(FilePathCache, GetFileIdInAfterPopulateIfEmpty)
{
cacheNotFilled.populateIfEmpty();
auto id = cacheNotFilled.filePathId("/path2/to/file.cpp");
ASSERT_THAT(id, Eq(72));
}
TEST_F(FilePathCache, DontPopulateIfNotEmpty)
{
cacheNotFilled.filePathId("/path/to/file.cpp");
cacheNotFilled.populateIfEmpty();
auto id = cacheNotFilled.filePathId("/path2/to/file.cpp");
ASSERT_FALSE(id.isValid());
}
TEST_F(FilePathCache, GetDirectoryIdAfterPopulateIfEmpty)
{
cacheNotFilled.populateIfEmpty();
auto id = cacheNotFilled.directoryPathId(42);
ASSERT_THAT(id, Eq(5));
}
TEST_F(FilePathCache, GetDirectoryPathAfterPopulateIfEmpty)
{
cacheNotFilled.populateIfEmpty();
auto path = cacheNotFilled.directoryPath(5);
ASSERT_THAT(path, Eq("/path/to"));
}
TEST_F(FilePathCache, GetFilePathAfterPopulateIfEmptye)
{
cacheNotFilled.populateIfEmpty();
auto path = cacheNotFilled.filePath(42);
ASSERT_THAT(path, Eq("/path/to/file.cpp"));
}
} // namespace } // namespace

View File

@@ -35,12 +35,12 @@ using ClangBackEnd::V2::FileContainers;
class GeneratedFiles : public testing::Test class GeneratedFiles : public testing::Test
{ {
protected: protected:
FileContainer file1{"/file1", "content1"}; FileContainer file1{"/file1", 1, "content1"};
FileContainer file1b{"/file1", "content1b"}; FileContainer file1b{"/file1", 1, "content1b"};
FileContainer file2{"/file2", "content2"}; FileContainer file2{"/file2", 2, "content2"};
FileContainer file2b{"/file2", "content2b"}; FileContainer file2b{"/file2", 2, "content2b"};
FileContainer file3{"/file3", "content3"}; FileContainer file3{"/file3", 3, "content3"};
FileContainer file4{"/file4", "content4"}; FileContainer file4{"/file4", 4, "content4"};
ClangBackEnd::GeneratedFiles generatedFiles; ClangBackEnd::GeneratedFiles generatedFiles;
}; };
@@ -76,7 +76,7 @@ TEST_F(GeneratedFiles, IsValidForNoGeneratedFiles)
TEST_F(GeneratedFiles, IsNotValidIfFilesWithNotContentExists) TEST_F(GeneratedFiles, IsNotValidIfFilesWithNotContentExists)
{ {
generatedFiles.update({{"/file2", ""}}); generatedFiles.update({{"/file2", 2, ""}});
ASSERT_FALSE(generatedFiles.isValid()); ASSERT_FALSE(generatedFiles.isValid());
} }
@@ -86,4 +86,15 @@ TEST_F(GeneratedFiles, IsValidIfAllFilesHasContent)
generatedFiles.update({file1, file2, file3, file4}); generatedFiles.update({file1, file2, file3, file4});
ASSERT_TRUE(generatedFiles.isValid()); ASSERT_TRUE(generatedFiles.isValid());
}} }
TEST_F(GeneratedFiles, GetFilePathIds)
{
generatedFiles.update({file3, file2, file1, file4});
auto ids = generatedFiles.filePathIds();
ASSERT_THAT(ids, ElementsAre(1, 2, 3, 4));
}
} // namespace

View File

@@ -106,7 +106,7 @@ void PrintTo(Utils::SmallStringView text, ::std::ostream *os);
void PrintTo(const Utils::SmallString &text, ::std::ostream *os); void PrintTo(const Utils::SmallString &text, ::std::ostream *os);
void PrintTo(const Utils::PathString &text, ::std::ostream *os); void PrintTo(const Utils::PathString &text, ::std::ostream *os);
} // namespace ProjectExplorer } // namespace Utils
namespace ClangBackEnd { namespace ClangBackEnd {
class SourceLocationEntry; class SourceLocationEntry;

View File

@@ -43,4 +43,5 @@ public:
MOCK_CONST_METHOD1(directoryPathId, MOCK_CONST_METHOD1(directoryPathId,
ClangBackEnd::DirectoryPathId(ClangBackEnd::FilePathId filePathId)); ClangBackEnd::DirectoryPathId(ClangBackEnd::FilePathId filePathId));
MOCK_METHOD1(addFilePaths, void(const ClangBackEnd::FilePaths &filePaths)); MOCK_METHOD1(addFilePaths, void(const ClangBackEnd::FilePaths &filePaths));
MOCK_METHOD0(populateIfEmpty, void());
}; };

View File

@@ -38,6 +38,7 @@ public:
void (const ClangBackEnd::FilePaths &filePaths)); void (const ClangBackEnd::FilePaths &filePaths));
MOCK_CONST_METHOD0(fileContainers, MOCK_CONST_METHOD0(fileContainers,
const ClangBackEnd::V2::FileContainers &()); const ClangBackEnd::V2::FileContainers &());
MOCK_CONST_METHOD0(filePathIds, ClangBackEnd::FilePathIds());
MOCK_CONST_METHOD0(isValid, bool()); MOCK_CONST_METHOD0(isValid, bool());
void update(ClangBackEnd::V2::FileContainers &&fileContainers) void update(ClangBackEnd::V2::FileContainers &&fileContainers)

View File

@@ -36,8 +36,11 @@ public:
MOCK_CONST_METHOD1( MOCK_CONST_METHOD1(
fetchProjectParts, fetchProjectParts,
ClangBackEnd::ProjectPartContainers(const ClangBackEnd::ProjectPartIds &projectPartIds)); ClangBackEnd::ProjectPartContainers(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_CONST_METHOD0(fetchAllProjectPartNamesAndIds, ClangBackEnd::Internal::ProjectPartNameIds());
MOCK_CONST_METHOD1(fetchProjectPartId, MOCK_CONST_METHOD1(fetchProjectPartId,
ClangBackEnd::ProjectPartId(Utils::SmallStringView projectPartName)); ClangBackEnd::ProjectPartId(Utils::SmallStringView projectPartName));
MOCK_CONST_METHOD1(fetchProjectPartIdUnguarded,
ClangBackEnd::ProjectPartId(Utils::SmallStringView projectPartName));
MOCK_CONST_METHOD1(fetchProjectPartName, MOCK_CONST_METHOD1(fetchProjectPartName,
Utils::PathString(ClangBackEnd::ProjectPartId projectPartId)); Utils::PathString(ClangBackEnd::ProjectPartId projectPartId));
MOCK_METHOD8(updateProjectPart, MOCK_METHOD8(updateProjectPart,

View File

@@ -109,6 +109,12 @@ std::vector<Sources::Source> MockSqliteReadStatement::values<Sources::Source, 3>
return valuesReturnStdVectorSource(reserveSize); return valuesReturnStdVectorSource(reserveSize);
} }
template<>
ProjectPartNameIds MockSqliteReadStatement::values<ProjectPartNameId, 2>(std::size_t reserveSize)
{
return valuesReturnProjectPartNameIds(reserveSize);
}
template <> template <>
Utils::optional<int> Utils::optional<int>
MockSqliteReadStatement::value<int>(const Utils::SmallStringView &text) MockSqliteReadStatement::value<int>(const Utils::SmallStringView &text)

View File

@@ -34,6 +34,7 @@
#include <projectpartartefact.h> #include <projectpartartefact.h>
#include <projectpartcontainer.h> #include <projectpartcontainer.h>
#include <projectpartpch.h> #include <projectpartpch.h>
#include <projectpartstoragestructs.h>
#include <sourceentry.h> #include <sourceentry.h>
#include <stringcachefwd.h> #include <stringcachefwd.h>
#include <symbol.h> #include <symbol.h>
@@ -59,6 +60,8 @@ using std::int64_t;
namespace Sources = ClangBackEnd::Sources; namespace Sources = ClangBackEnd::Sources;
using ClangBackEnd::PrecompiledHeaderTimeStamps; using ClangBackEnd::PrecompiledHeaderTimeStamps;
using ClangBackEnd::UsedMacros; using ClangBackEnd::UsedMacros;
using ClangBackEnd::Internal::ProjectPartNameId;
using ClangBackEnd::Internal::ProjectPartNameIds;
using ClangRefactoring::Symbol; using ClangRefactoring::Symbol;
using ClangRefactoring::Symbols; using ClangRefactoring::Symbols;
@@ -91,6 +94,8 @@ public:
MOCK_METHOD2(valuesReturnFilePathIds, FilePathIds(std::size_t, int)); MOCK_METHOD2(valuesReturnFilePathIds, FilePathIds(std::size_t, int));
MOCK_METHOD1(valuesReturnProjectPartNameIds, ProjectPartNameIds(std::size_t));
MOCK_METHOD1(valueReturnInt32, Utils::optional<int>(Utils::SmallStringView)); MOCK_METHOD1(valueReturnInt32, Utils::optional<int>(Utils::SmallStringView));
MOCK_METHOD2(valueReturnInt32, Utils::optional<int>(int, Utils::SmallStringView)); MOCK_METHOD2(valueReturnInt32, Utils::optional<int>(int, Utils::SmallStringView));
@@ -226,9 +231,11 @@ std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directo
template<> template<>
std::vector<Sources::Source> MockSqliteReadStatement::values<Sources::Source, 3>(std::size_t reserveSize); std::vector<Sources::Source> MockSqliteReadStatement::values<Sources::Source, 3>(std::size_t reserveSize);
template <> template<>
Utils::optional<int> ProjectPartNameIds MockSqliteReadStatement::values<ProjectPartNameId, 2>(std::size_t reserveSize);
MockSqliteReadStatement::value<int>(const Utils::SmallStringView&);
template<>
Utils::optional<int> MockSqliteReadStatement::value<int>(const Utils::SmallStringView &);
template <> template <>
Utils::optional<int> Utils::optional<int>

View File

@@ -34,7 +34,6 @@ class MockSymbolIndexerTaskQueue : public ClangBackEnd::SymbolIndexerTaskQueueIn
public: public:
MOCK_METHOD1(addOrUpdateTasks, MOCK_METHOD1(addOrUpdateTasks,
void (std::vector<ClangBackEnd::SymbolIndexerTask> &&tasks)); void (std::vector<ClangBackEnd::SymbolIndexerTask> &&tasks));
MOCK_METHOD1(removeTasks, MOCK_METHOD1(removeTasks, void(const ClangBackEnd::ProjectPartIds &projectPartIds));
void (const std::vector<int> &projectPartIds));
MOCK_METHOD0(processEntries, void()); MOCK_METHOD0(processEntries, void());
}; };

View File

@@ -91,7 +91,7 @@ protected:
ClangBackEnd::FilePathId id(ClangBackEnd::FilePathView path) ClangBackEnd::FilePathId id(ClangBackEnd::FilePathView path)
{ {
return creator.filePathCache().filePathId(path); return filePathCache.filePathId(path);
} }
FilePathIds sorted(FilePathIds &&filePathIds) FilePathIds sorted(FilePathIds &&filePathIds)
@@ -104,17 +104,17 @@ protected:
protected: protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
ClangBackEnd::FilePathCaching filePathCache{database};
FilePath main1Path = TESTDATA_DIR "/builddependencycollector/project/main3.cpp"; FilePath main1Path = TESTDATA_DIR "/builddependencycollector/project/main3.cpp";
FilePath main2Path = TESTDATA_DIR "/builddependencycollector/project/main2.cpp"; FilePath main2Path = TESTDATA_DIR "/builddependencycollector/project/main2.cpp";
FilePath header1Path = TESTDATA_DIR "/builddependencycollector/project/header1.h"; FilePath header1Path = TESTDATA_DIR "/builddependencycollector/project/header1.h";
FilePath header2Path = TESTDATA_DIR "/builddependencycollector/project/header2.h"; FilePath header2Path = TESTDATA_DIR "/builddependencycollector/project/header2.h";
FilePath generatedFilePath = TESTDATA_DIR "/builddependencycollector/project/generated_file.h"; FilePath generatedFilePath = TESTDATA_DIR "/builddependencycollector/project/generated_file.h";
TestEnvironment environment; TestEnvironment environment;
FileContainer generatedFile{generatedFilePath.clone(), "#pragma once", {}}; FileContainer generatedFile{generatedFilePath.clone(), id(generatedFilePath), "#pragma once", {}};
NiceMock<MockPchManagerClient> mockPchManagerClient; NiceMock<MockPchManagerClient> mockPchManagerClient;
NiceMock<MockClangPathWatcher> mockClangPathWatcher; NiceMock<MockClangPathWatcher> mockClangPathWatcher;
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage; NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
ClangBackEnd::FilePathCaching filePathCache{database};
ClangBackEnd::PchCreator creator{environment, ClangBackEnd::PchCreator creator{environment,
filePathCache, filePathCache,
mockPchManagerClient, mockPchManagerClient,

View File

@@ -117,7 +117,7 @@ TEST_F(PchManagerClientServerInProcess, SendUpdateProjectPartsMessage)
TEST_F(PchManagerClientServerInProcess, SendUpdateGeneratedFilesMessage) TEST_F(PchManagerClientServerInProcess, SendUpdateGeneratedFilesMessage)
{ {
FileContainer fileContainer{{"/path/to/", "file"}, "content", {}}; FileContainer fileContainer{{"/path/to/", "file"}, 1, "content", {}};
UpdateGeneratedFilesMessage message{{fileContainer}}; UpdateGeneratedFilesMessage message{{fileContainer}};
EXPECT_CALL(mockPchManagerServer, updateGeneratedFiles(message)); EXPECT_CALL(mockPchManagerServer, updateGeneratedFiles(message));

View File

@@ -27,6 +27,7 @@
#include "mockbuilddependenciesstorage.h" #include "mockbuilddependenciesstorage.h"
#include "mockclangpathwatcher.h" #include "mockclangpathwatcher.h"
#include "mockfilepathcaching.h"
#include "mockgeneratedfiles.h" #include "mockgeneratedfiles.h"
#include "mockpchmanagerclient.h" #include "mockpchmanagerclient.h"
#include "mockpchtaskgenerator.h" #include "mockpchtaskgenerator.h"
@@ -77,11 +78,13 @@ protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database}; ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::FilePathCaching filePathCache{database};
NiceMock<MockFilePathCaching> mockFilePathCache;
ClangBackEnd::PchManagerServer server{mockClangPathWatcher, ClangBackEnd::PchManagerServer server{mockClangPathWatcher,
mockPchTaskGenerator, mockPchTaskGenerator,
mockProjectPartsManager, mockProjectPartsManager,
mockGeneratedFiles, mockGeneratedFiles,
mockBuildDependenciesStorage}; mockBuildDependenciesStorage,
mockFilePathCache};
NiceMock<MockPchManagerClient> mockPchManagerClient; NiceMock<MockPchManagerClient> mockPchManagerClient;
ClangBackEnd::ProjectPartId projectPartId1{1}; ClangBackEnd::ProjectPartId projectPartId1{1};
ClangBackEnd::ProjectPartId projectPartId2{2}; ClangBackEnd::ProjectPartId projectPartId2{2};
@@ -98,7 +101,7 @@ protected:
projectPartId1, projectPartId1,
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}}, {{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, {{TESTDATA_DIR "/symbolscollector/include", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}}, {{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header1Path)}, {id(header1Path)},
{id(main1Path)}, {id(main1Path)},
@@ -110,7 +113,7 @@ protected:
{"-x", "c++-header", "-Wno-pragma-once-outside-header"}, {"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}}, {{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, {{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}}, {{TESTDATA_DIR "/builddependencycollector", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header2Path)}, {id(header2Path)},
{id(main2Path)}, {id(main2Path)},
Utils::Language::C, Utils::Language::C,
@@ -165,7 +168,7 @@ protected:
std::vector<ProjectPartContainer> projectParts2{projectPart2}; std::vector<ProjectPartContainer> projectParts2{projectPart2};
std::vector<ProjectPartContainer> projectParts3{projectPart3}; std::vector<ProjectPartContainer> projectParts3{projectPart3};
std::vector<ProjectPartContainer> projectParts4{projectPart3, projectPart4}; std::vector<ProjectPartContainer> projectParts4{projectPart3, projectPart4};
FileContainer generatedFile{{"/path/to/", "file"}, "content", {}}; FileContainer generatedFile{{"/path/to/", "file"}, id("/path/to/file"), "content", {}};
ClangBackEnd::UpdateProjectPartsMessage updateProjectPartsMessage{ ClangBackEnd::UpdateProjectPartsMessage updateProjectPartsMessage{
Utils::clone(projectParts), {"toolChainArgument"}}; Utils::clone(projectParts), {"toolChainArgument"}};
ClangBackEnd::RemoveProjectPartsMessage removeProjectPartsMessage{ ClangBackEnd::RemoveProjectPartsMessage removeProjectPartsMessage{
@@ -226,7 +229,8 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier)
mockPchTaskGenerator, mockPchTaskGenerator,
mockProjectPartsManager, mockProjectPartsManager,
mockGeneratedFiles, mockGeneratedFiles,
mockBuildDependenciesStorage}; mockBuildDependenciesStorage,
filePathCache};
} }
TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds) TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds)
@@ -419,4 +423,20 @@ TEST_F(PchManagerServer, SentUpToDateProjectPartIdsToClient)
server.updateProjectParts(updateProjectPartsMessage.clone()); server.updateProjectParts(updateProjectPartsMessage.clone());
} }
TEST_F(PchManagerServer, AddingIncludesToFileCacheForProjectUpdates)
{
InSequence s;
EXPECT_CALL(mockFilePathCache, populateIfEmpty());
EXPECT_CALL(mockFilePathCache,
addFilePaths(AllOf(
Contains(Eq(TESTDATA_DIR "/symbolscollector/include/unmodified_header.h")),
Contains(Eq(TESTDATA_DIR "/symbolscollector/include/unmodified_header2.h")),
Contains(Eq(TESTDATA_DIR "/builddependencycollector/project/header2.h")),
Contains(Eq(TESTDATA_DIR "/builddependencycollector/external/external3.h")))));
EXPECT_CALL(mockProjectPartsManager, update(_));
server.updateProjectParts(updateProjectPartsMessage.clone());
}
} // namespace } // namespace

View File

@@ -29,11 +29,13 @@
#include <builddependenciesstorage.h> #include <builddependenciesstorage.h>
#include <projectpartsstorage.h> #include <projectpartsstorage.h>
#include <projectpartstoragestructs.h>
#include <refactoringdatabaseinitializer.h> #include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h> #include <sqlitedatabase.h>
#include <sqlitereadstatement.h> #include <sqlitereadstatement.h>
#include <sqlitewritestatement.h> #include <sqlitewritestatement.h>
#include <symbolstorage.h> #include <symbolstorage.h>
namespace { namespace {
using ClangBackEnd::FilePathId; using ClangBackEnd::FilePathId;
@@ -107,6 +109,7 @@ protected:
MockSqliteReadStatement &fetchProjectPrecompiledHeaderPathStatement = storage.fetchProjectPrecompiledHeaderBuildTimeStatement; MockSqliteReadStatement &fetchProjectPrecompiledHeaderPathStatement = storage.fetchProjectPrecompiledHeaderBuildTimeStatement;
MockSqliteReadStatement &fetchProjectPrecompiledHeaderBuildTimeStatement = storage.fetchProjectPrecompiledHeaderBuildTimeStatement; MockSqliteReadStatement &fetchProjectPrecompiledHeaderBuildTimeStatement = storage.fetchProjectPrecompiledHeaderBuildTimeStatement;
MockSqliteWriteStatement &resetDependentIndexingTimeStampsStatement = storage.resetDependentIndexingTimeStampsStatement; MockSqliteWriteStatement &resetDependentIndexingTimeStampsStatement = storage.resetDependentIndexingTimeStampsStatement;
MockSqliteReadStatement &fetchAllProjectPartNamesAndIdsStatement = storage.fetchAllProjectPartNamesAndIdsStatement;
IncludeSearchPaths systemIncludeSearchPaths{{"/includes", 1, IncludeSearchPathType::BuiltIn}, IncludeSearchPaths systemIncludeSearchPaths{{"/includes", 1, IncludeSearchPathType::BuiltIn},
{"/other/includes", 2, IncludeSearchPathType::System}}; {"/other/includes", 2, IncludeSearchPathType::System}};
IncludeSearchPaths projectIncludeSearchPaths{{"/project/includes", 1, IncludeSearchPathType::User}, IncludeSearchPaths projectIncludeSearchPaths{{"/project/includes", 1, IncludeSearchPathType::User},
@@ -124,6 +127,7 @@ protected:
Utils::Language::Cxx, Utils::Language::Cxx,
Utils::LanguageVersion::CXX11, Utils::LanguageVersion::CXX11,
Utils::LanguageExtension::None}; Utils::LanguageExtension::None};
ClangBackEnd::Internal::ProjectPartNameIds projectPartNameIds{{"projectPartName", 2}};
}; };
TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithNonExistingProjectPartName) TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithNonExistingProjectPartName)
@@ -139,6 +143,17 @@ TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithNonExistingProjectPartName)
storage.fetchProjectPartId("test"); storage.fetchProjectPartId("test");
} }
TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithNonExistingProjectPartNameUnguarded)
{
InSequence s;
EXPECT_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")));
EXPECT_CALL(insertProjectPartNameStatement, write(TypedEq<Utils::SmallStringView>("test")));
storage.fetchProjectPartIdUnguarded("test");
}
TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithExistingProjectPart) TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithExistingProjectPart)
{ {
InSequence s; InSequence s;
@@ -153,6 +168,18 @@ TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithExistingProjectPart)
storage.fetchProjectPartId("test"); storage.fetchProjectPartId("test");
} }
TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithExistingProjectPartUnguarded)
{
InSequence s;
EXPECT_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")))
.WillOnce(Return(Utils::optional<ProjectPartId>{20}));
EXPECT_CALL(insertProjectPartNameStatement, write(TypedEq<Utils::SmallStringView>("test"))).Times(0);
storage.fetchProjectPartIdUnguarded("test");
}
TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithBusyDatabaset) TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithBusyDatabaset)
{ {
InSequence s; InSequence s;
@@ -184,6 +211,18 @@ TEST_F(ProjectPartsStorage, FetchProjectIdWithNonExistingProjectPartName)
ASSERT_THAT(id.projectPathId, 21); ASSERT_THAT(id.projectPathId, 21);
} }
TEST_F(ProjectPartsStorage, FetchProjectIdWithNonExistingProjectPartNameUnguarded)
{
ON_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")))
.WillByDefault(Return(Utils::optional<ProjectPartId>{}));
ON_CALL(mockDatabase, lastInsertedRowId()).WillByDefault(Return(21));
auto id = storage.fetchProjectPartIdUnguarded("test");
ASSERT_THAT(id.projectPathId, 21);
}
TEST_F(ProjectPartsStorage, FetchProjectIdWithNonExistingProjectPartNameAndIsBusy) TEST_F(ProjectPartsStorage, FetchProjectIdWithNonExistingProjectPartNameAndIsBusy)
{ {
InSequence s; InSequence s;
@@ -211,6 +250,17 @@ TEST_F(ProjectPartsStorage, FetchProjectIdWithExistingProjectPartName)
ASSERT_THAT(id.projectPathId, 20); ASSERT_THAT(id.projectPathId, 20);
} }
TEST_F(ProjectPartsStorage, FetchProjectIdWithExistingProjectPartNameUnguarded)
{
ON_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")))
.WillByDefault(Return(Utils::optional<ProjectPartId>{20}));
auto id = storage.fetchProjectPartIdUnguarded("test");
ASSERT_THAT(id.projectPathId, 20);
}
TEST_F(ProjectPartsStorage, FetchProjectPartName) TEST_F(ProjectPartsStorage, FetchProjectPartName)
{ {
InSequence s; InSequence s;
@@ -418,6 +468,7 @@ TEST_F(ProjectPartsStorage, FetchProjectPartArtefactBySourceIdCallsValueInStatem
storage.fetchProjectPartArtefact(FilePathId{1}); storage.fetchProjectPartArtefact(FilePathId{1});
} }
TEST_F(ProjectPartsStorage, FetchProjectPartArtefactBySourceIdReturnArtefact) TEST_F(ProjectPartsStorage, FetchProjectPartArtefactBySourceIdReturnArtefact)
{ {
EXPECT_CALL(getProjectPartArtefactsBySourceId, valueReturnProjectPartArtefact(1)) EXPECT_CALL(getProjectPartArtefactsBySourceId, valueReturnProjectPartArtefact(1))
@@ -495,6 +546,34 @@ TEST_F(ProjectPartsStorage, ResetDependentIndexingTimeStampsIsBusy)
storage.resetIndexingTimeStamps({projectPart1, projectPart2}); storage.resetIndexingTimeStamps({projectPart1, projectPart2});
} }
TEST_F(ProjectPartsStorage, FetchAllProjectPartNamesAndIdsCalls)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchAllProjectPartNamesAndIdsStatement, valuesReturnProjectPartNameIds(_))
.WillRepeatedly(Return(projectPartNameIds));
EXPECT_CALL(mockDatabase, commit());
storage.fetchAllProjectPartNamesAndIds();
}
TEST_F(ProjectPartsStorage, FetchAllProjectPartNamesAndIdsCallsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchAllProjectPartNamesAndIdsStatement, valuesReturnProjectPartNameIds(_))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchAllProjectPartNamesAndIdsStatement, valuesReturnProjectPartNameIds(_))
.WillRepeatedly(Return(projectPartNameIds));
EXPECT_CALL(mockDatabase, commit());
storage.fetchAllProjectPartNamesAndIds();
}
class ProjectPartsStorageSlow : public testing::Test, public Data class ProjectPartsStorageSlow : public testing::Test, public Data
{ {
using Storage = ClangBackEnd::ProjectPartsStorage<Sqlite::Database>; using Storage = ClangBackEnd::ProjectPartsStorage<Sqlite::Database>;
@@ -530,6 +609,15 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectPartId)
ASSERT_THAT(first, Eq(second)); ASSERT_THAT(first, Eq(second));
} }
TEST_F(ProjectPartsStorageSlow, FetchProjectPartIdUnguarded)
{
auto first = storage.fetchProjectPartId("test");
auto second = storage.fetchProjectPartIdUnguarded("test");
ASSERT_THAT(first, Eq(second));
}
TEST_F(ProjectPartsStorageSlow, FetchProjectParts) TEST_F(ProjectPartsStorageSlow, FetchProjectParts)
{ {
projectPart1.projectPartId = storage.fetchProjectPartId("project1"); projectPart1.projectPartId = storage.fetchProjectPartId("project1");
@@ -563,4 +651,16 @@ TEST_F(ProjectPartsStorageSlow, ResetDependentIndexingTimeStamps)
SourceTimeStamp{10, 34})); SourceTimeStamp{10, 34}));
} }
TEST_F(ProjectPartsStorageSlow, FetchAllProjectPartNamesAndIdsy)
{
using ClangBackEnd::Internal::ProjectPartNameId;
auto id = storage.fetchProjectPartId("projectPartName");
auto id2 = storage.fetchProjectPartId("projectPartName2");
auto values = storage.fetchAllProjectPartNamesAndIds();
ASSERT_THAT(values,
UnorderedElementsAre(ProjectPartNameId{"projectPartName", id},
ProjectPartNameId{"projectPartName2", id2}));
}
} // namespace } // namespace

View File

@@ -66,10 +66,11 @@ using testing::NiceMock;
using testing::AnyNumber; using testing::AnyNumber;
using ClangBackEnd::CompilerMacro; using ClangBackEnd::CompilerMacro;
using ClangBackEnd::FilePath;
using ClangBackEnd::IncludeSearchPath; using ClangBackEnd::IncludeSearchPath;
using ClangBackEnd::IncludeSearchPathType; using ClangBackEnd::IncludeSearchPathType;
using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::ProjectPartContainer; using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::V2::FileContainer;
using CppTools::CompilerOptionsBuilder; using CppTools::CompilerOptionsBuilder;
using ProjectExplorer::HeaderPath; using ProjectExplorer::HeaderPath;
@@ -182,9 +183,18 @@ protected:
CppTools::ProjectPart nonBuildingProjectPart; CppTools::ProjectPart nonBuildingProjectPart;
ProjectPartContainer expectedContainer; ProjectPartContainer expectedContainer;
ProjectPartContainer expectedContainer2; ProjectPartContainer expectedContainer2;
FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}}; FileContainer generatedFile{{"/path/to", "header1.h"},
FileContainer generatedFile2{{"/path/to2", "header1.h"}, "content", {}}; filePathCache.filePathId(FilePath{"/path/to", "header1.h"}),
FileContainer generatedFile3{{"/path/to", "header2.h"}, "content", {}}; "content",
{}};
FileContainer generatedFile2{{"/path/to2", "header1.h"},
filePathCache.filePathId(FilePath{"/path/to2", "header1.h"}),
"content",
{}};
FileContainer generatedFile3{{"/path/to", "header2.h"},
filePathCache.filePathId(FilePath{"/path/to", "header2.h"}),
"content",
{}};
}; };
TEST_F(ProjectUpdater, CallUpdateProjectParts) TEST_F(ProjectUpdater, CallUpdateProjectParts)
@@ -271,6 +281,7 @@ TEST_F(ProjectUpdater, CallPrecompiledHeaderRemovedInPchManagerProjectUpdater)
TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer) TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer)
{ {
updater.setExcludedPaths({"/path/to/header1.h"}); updater.setExcludedPaths({"/path/to/header1.h"});
updater.fetchProjectPartIds({&projectPart});
auto container = updater.toProjectPartContainer(&projectPart); auto container = updater.toProjectPartContainer(&projectPart);
@@ -279,21 +290,23 @@ TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer)
TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainersHaveSameSizeLikeProjectParts) TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainersHaveSameSizeLikeProjectParts)
{ {
updater.fetchProjectPartIds({&projectPart, &nonBuildingProjectPart});
auto containers = updater.toProjectPartContainers( auto containers = updater.toProjectPartContainers(
{&projectPart, &projectPart, &nonBuildingProjectPart}); {&projectPart, &projectPart, &nonBuildingProjectPart});
ASSERT_THAT(containers, SizeIs(2)); ASSERT_THAT(containers, SizeIs(2));
} }
TEST_F(ProjectUpdater, CallStorageInsideTransaction) TEST_F(ProjectUpdater, ProjectPartIdsPrefetchingInsideTransaction)
{ {
InSequence s; InSequence s;
CppTools::ProjectPart projectPart; CppTools::ProjectPart projectPart;
projectPart.project = &project; projectPart.project = &project;
projectPart.displayName = "project"; projectPart.displayName = "project";
Utils::SmallString projectPartName = projectPart.id(); Utils::SmallString projectPartName = projectPart.id();
MockSqliteTransactionBackend mockSqliteTransactionBackend; NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
MockProjectPartsStorage mockProjectPartsStorage; NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
ON_CALL(mockProjectPartsStorage, transactionBackend()) ON_CALL(mockProjectPartsStorage, transactionBackend())
.WillByDefault(ReturnRef(mockSqliteTransactionBackend)); .WillByDefault(ReturnRef(mockSqliteTransactionBackend));
ClangPchManager::ClangIndexingSettingsManager settingsManager; ClangPchManager::ClangIndexingSettingsManager settingsManager;
@@ -302,9 +315,11 @@ TEST_F(ProjectUpdater, CallStorageInsideTransaction)
mockProjectPartsStorage, mockProjectPartsStorage,
settingsManager}; settingsManager};
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartId(Eq(projectPartName))); EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartIdUnguarded(Eq(projectPartName)));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
updater.toProjectPartContainers({&projectPart}); updater.fetchProjectPartIds({&projectPart});
} }
TEST_F(ProjectUpdater, CreateSortedExcludedPaths) TEST_F(ProjectUpdater, CreateSortedExcludedPaths)
@@ -476,7 +491,8 @@ TEST_F(ProjectUpdater, AddProjectFilesToFilePathCache)
NiceMock<MockFilePathCaching> mockFilePathCaching; NiceMock<MockFilePathCaching> mockFilePathCaching;
ClangPchManager::ProjectUpdater updater{mockPchManagerServer, ClangPchManager::ProjectUpdater updater{mockPchManagerServer,
mockFilePathCaching, mockFilePathCaching,
projectPartsStorage}; projectPartsStorage,
settingsManager};
EXPECT_CALL(mockFilePathCaching, EXPECT_CALL(mockFilePathCaching,
addFilePaths(UnorderedElementsAre(Eq(headerPaths[0]), addFilePaths(UnorderedElementsAre(Eq(headerPaths[0]),
@@ -487,6 +503,39 @@ TEST_F(ProjectUpdater, AddProjectFilesToFilePathCache)
updater.updateProjectParts({&projectPart}, {}); updater.updateProjectParts({&projectPart}, {});
} }
// test for update many time and get the same id TEST_F(ProjectUpdater, FillProjectPartIdCacheAtCreation)
{
NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
EXPECT_CALL(mockProjectPartsStorage, fetchAllProjectPartNamesAndIds());
ClangPchManager::ProjectUpdater updater{mockPchManagerServer,
filePathCache,
mockProjectPartsStorage,
settingsManager};
}
TEST_F(ProjectUpdater, DontFetchProjectPartIdFromDatabaseIfItIsInCache)
{
projectPart.files.clear();
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
ON_CALL(mockProjectPartsStorage, transactionBackend())
.WillByDefault(ReturnRef(mockSqliteTransactionBackend));
ON_CALL(mockProjectPartsStorage, fetchAllProjectPartNamesAndIds())
.WillByDefault(Return(
ClangBackEnd::Internal::ProjectPartNameIds{{Utils::PathString(projectPart.id()), 55}}));
ClangPchManager::ProjectUpdater updater{mockPchManagerServer,
filePathCache,
mockProjectPartsStorage,
settingsManager};
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin()).Times(0);
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartId(_)).Times(0);
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartIdUnguarded(_)).Times(0);
EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0);
updater.updateProjectParts({&projectPart}, {});
}
} // namespace } // namespace

View File

@@ -129,8 +129,8 @@ TEST_F(RefactoringClientServerInProcess, RequestSourceRangesAndDiagnosticsForQue
{ {
RequestSourceRangesForQueryMessage message{ RequestSourceRangesForQueryMessage message{
"functionDecl()", "functionDecl()",
{{{TESTDATA_DIR, "query_simplefunction.cpp"}, "void f();", {"cc"}, 1}}, {{{TESTDATA_DIR, "query_simplefunction.cpp"}, 1, "void f();", {"cc"}, 1}},
{{{TESTDATA_DIR, "query_simplefunction.h"}, "void f();", {}, 1}}}; {{{TESTDATA_DIR, "query_simplefunction.h"}, 2, "void f();", {}, 1}}};
EXPECT_CALL(mockRefactoringServer, requestSourceRangesForQueryMessage(message)); EXPECT_CALL(mockRefactoringServer, requestSourceRangesForQueryMessage(message));
@@ -143,12 +143,13 @@ TEST_F(RefactoringClientServerInProcess, RequestSourceRangesForQueryMessage)
RequestSourceRangesForQueryMessage message{ RequestSourceRangesForQueryMessage message{
"functionDecl()", "functionDecl()",
{{{TESTDATA_DIR, "query_simplefunction.cpp"}, {{{TESTDATA_DIR, "query_simplefunction.cpp"},
1,
"void f();", "void f();",
{ {
"cc", "cc",
}, },
1}}, 1}},
{{{TESTDATA_DIR, "query_simplefunction.h"}, "void f();", {}, 1}}}; {{{TESTDATA_DIR, "query_simplefunction.h"}, 2, "void f();", {}, 1}}};
EXPECT_CALL(mockRefactoringServer, requestSourceRangesForQueryMessage(message)); EXPECT_CALL(mockRefactoringServer, requestSourceRangesForQueryMessage(message));
@@ -182,7 +183,7 @@ TEST_F(RefactoringClientServerInProcess, SendUpdateProjectPartsMessage)
TEST_F(RefactoringClientServerInProcess, SendUpdateGeneratedFilesMessage) TEST_F(RefactoringClientServerInProcess, SendUpdateGeneratedFilesMessage)
{ {
FileContainer fileContainer{{"/path/to/", "file"}, "content", {}}; FileContainer fileContainer{{"/path/to/", "file"}, 1, "content", {}};
UpdateGeneratedFilesMessage message{{fileContainer}}; UpdateGeneratedFilesMessage message{{fileContainer}};
EXPECT_CALL(mockRefactoringServer, updateGeneratedFiles(message)); EXPECT_CALL(mockRefactoringServer, updateGeneratedFiles(message));

View File

@@ -64,6 +64,10 @@ MATCHER_P(IsProjectPartContainer,
class RefactoringProjectUpdater : public testing::Test class RefactoringProjectUpdater : public testing::Test
{ {
protected: protected:
RefactoringProjectUpdater()
{
ON_CALL(mockProjectPartsStorage, transactionBackend()).WillByDefault(ReturnRef(database));
}
ProjectPart::Ptr createProjectPart(const char *name) ProjectPart::Ptr createProjectPart(const char *name)
{ {
ProjectPart::Ptr projectPart{new ProjectPart}; ProjectPart::Ptr projectPart{new ProjectPart};
@@ -115,8 +119,6 @@ TEST_F(RefactoringProjectUpdater, UpdateProjectPart)
.WillRepeatedly(Return(QString(" project1"))); .WillRepeatedly(Return(QString(" project1")));
EXPECT_CALL(mockCppModelManager, projectPartForId(Eq(QString(" project1")))) EXPECT_CALL(mockCppModelManager, projectPartForId(Eq(QString(" project1"))))
.WillRepeatedly(Return(createProjectPart("project1"))); .WillRepeatedly(Return(createProjectPart("project1")));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartId(Eq(" project1")))
.WillOnce(Return(ClangBackEnd::ProjectPartId{3}));
EXPECT_CALL(mockRefactoringServer, EXPECT_CALL(mockRefactoringServer,
updateProjectParts(Field(&UpdateProjectPartsMessage::projectsParts, updateProjectParts(Field(&UpdateProjectPartsMessage::projectsParts,
ElementsAre(IsProjectPartContainer(3))))); ElementsAre(IsProjectPartContainer(3)))));

View File

@@ -26,6 +26,7 @@
#include "googletest.h" #include "googletest.h"
#include "filesystem-utilities.h" #include "filesystem-utilities.h"
#include "mockfilepathcaching.h"
#include "mockrefactoringclient.h" #include "mockrefactoringclient.h"
#include "mocksymbolindexing.h" #include "mocksymbolindexing.h"
#include "sourcerangecontainer-matcher.h" #include "sourcerangecontainer-matcher.h"
@@ -98,7 +99,11 @@ protected:
ClangBackEnd::GeneratedFiles generatedFiles; ClangBackEnd::GeneratedFiles generatedFiles;
ClangBackEnd::RefactoringServer refactoringServer{mockSymbolIndexing, filePathCache, generatedFiles}; ClangBackEnd::RefactoringServer refactoringServer{mockSymbolIndexing, filePathCache, generatedFiles};
Utils::SmallString sourceContent{"void f()\n {}"}; Utils::SmallString sourceContent{"void f()\n {}"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, sourceContent.clone(), {"cc"}}; ClangBackEnd::FilePath filePath{TESTDATA_DIR, "query_simplefunction.cpp"};
FileContainer source{filePath.clone(),
filePathCache.filePathId(filePath),
sourceContent.clone(),
{"cc"}};
QTemporaryFile temporaryFile{Utils::TemporaryDirectory::masterDirectoryPath() QTemporaryFile temporaryFile{Utils::TemporaryDirectory::masterDirectoryPath()
+ "/clangQuery-XXXXXX.cpp"}; + "/clangQuery-XXXXXX.cpp"};
int processingSlotCount = 2; int processingSlotCount = 2;
@@ -126,9 +131,13 @@ TEST_F(RefactoringServerSlowTest, RequestSingleSourceRangesAndDiagnosticsWithUns
{ {
Utils::SmallString unsavedContent{"void f();"}; Utils::SmallString unsavedContent{"void f();"};
FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"},
filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.cpp"}),
"#include \"query_simplefunction.h\"", "#include \"query_simplefunction.h\"",
{"cc"}}; {"cc"}};
FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"}, unsavedContent.clone(), {}}; FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"},
filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.h"}),
unsavedContent.clone(),
{}};
RequestSourceRangesForQueryMessage message{"functionDecl()", {source.clone()}, {unsaved.clone()}}; RequestSourceRangesForQueryMessage message{"functionDecl()", {source.clone()}, {unsaved.clone()}};
EXPECT_CALL(mockRefactoringClient, EXPECT_CALL(mockRefactoringClient,
@@ -240,6 +249,8 @@ TEST_F(RefactoringServerSlowTest, ForValidRequestSourceRangesAndDiagnosticsGetSo
{ {
RequestSourceRangesAndDiagnosticsForQueryMessage message("functionDecl()", RequestSourceRangesAndDiagnosticsForQueryMessage message("functionDecl()",
{FilePath(temporaryFile.fileName()), {FilePath(temporaryFile.fileName()),
filePathCache.filePathId(FilePath(
temporaryFile.fileName())),
"void f() {}", "void f() {}",
{"cc"}}); {"cc"}});
@@ -259,6 +270,8 @@ TEST_F(RefactoringServerSlowTest, ForInvalidRequestSourceRangesAndDiagnosticsGet
{ {
RequestSourceRangesAndDiagnosticsForQueryMessage message("func()", RequestSourceRangesAndDiagnosticsForQueryMessage message("func()",
{FilePath(temporaryFile.fileName()), {FilePath(temporaryFile.fileName()),
filePathCache.filePathId(FilePath(
temporaryFile.fileName())),
"void f() {}", "void f() {}",
{"cc"}}); {"cc"}});
@@ -277,6 +290,7 @@ TEST_F(RefactoringServerSlowTest, ForInvalidRequestSourceRangesAndDiagnosticsGet
TEST_F(RefactoringServer, UpdateGeneratedFilesSetMemberWhichIsUsedForSymbolIndexing) TEST_F(RefactoringServer, UpdateGeneratedFilesSetMemberWhichIsUsedForSymbolIndexing)
{ {
FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"}, FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"},
filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.h"}),
"void f();", "void f();",
{}}}; {}}};
@@ -288,6 +302,7 @@ TEST_F(RefactoringServer, UpdateGeneratedFilesSetMemberWhichIsUsedForSymbolIndex
TEST_F(RefactoringServer, RemoveGeneratedFilesSetMemberWhichIsUsedForSymbolIndexing) TEST_F(RefactoringServer, RemoveGeneratedFilesSetMemberWhichIsUsedForSymbolIndexing)
{ {
FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"}, FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"},
filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.h"}),
"void f();", "void f();",
{}}}; {}}};
refactoringServer.updateGeneratedFiles(Utils::clone(unsaved)); refactoringServer.updateGeneratedFiles(Utils::clone(unsaved));
@@ -297,8 +312,12 @@ TEST_F(RefactoringServer, RemoveGeneratedFilesSetMemberWhichIsUsedForSymbolIndex
ASSERT_THAT(generatedFiles.fileContainers(), IsEmpty()); ASSERT_THAT(generatedFiles.fileContainers(), IsEmpty());
} }
TEST_F(RefactoringServer, UpdateProjectPartsCallsSymbolIndexingUpdateProjectParts) TEST_F(RefactoringServer, UpdateProjectPartsCalls)
{ {
NiceMock<MockFilePathCaching> mockFilePathCaching;
ClangBackEnd::RefactoringServer refactoringServer{mockSymbolIndexing,
mockFilePathCaching,
generatedFiles};
ProjectPartContainers projectParts{ ProjectPartContainers projectParts{
{{1, {{1,
{"-I", TESTDATA_DIR}, {"-I", TESTDATA_DIR},
@@ -313,8 +332,8 @@ TEST_F(RefactoringServer, UpdateProjectPartsCallsSymbolIndexingUpdateProjectPart
Utils::LanguageVersion::C11, Utils::LanguageVersion::C11,
Utils::LanguageExtension::All}}}; Utils::LanguageExtension::All}}};
EXPECT_CALL(mockSymbolIndexing, EXPECT_CALL(mockFilePathCaching, populateIfEmpty());
updateProjectParts(projectParts)); EXPECT_CALL(mockSymbolIndexing, updateProjectParts(projectParts));
refactoringServer.updateProjectParts({Utils::clone(projectParts), {}}); refactoringServer.updateProjectParts({Utils::clone(projectParts), {}});
} }

View File

@@ -203,6 +203,7 @@ protected:
Utils::LanguageVersion::CXX14, Utils::LanguageVersion::CXX14,
Utils::LanguageExtension::None}; Utils::LanguageExtension::None};
FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"}, FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"},
filePathId(TESTDATA_DIR "/query_simplefunction.h"),
"void f();", "void f();",
{}}}; {}}};
SymbolEntries symbolEntries{{1, {"function", "function", SymbolKind::Function}}}; SymbolEntries symbolEntries{{1, {"function", "function", SymbolKind::Function}}};

View File

@@ -264,8 +264,10 @@ TEST_F(SymbolsCollector, ReferencedSymboldMatchesLocation)
TEST_F(SymbolsCollector, DISABLED_ON_WINDOWS(CollectInUnsavedFile)) TEST_F(SymbolsCollector, DISABLED_ON_WINDOWS(CollectInUnsavedFile))
{ {
FileContainers unsaved{ FileContainers unsaved{{{TESTDATA_DIR, "symbolscollector/generated_file.h"},
{{TESTDATA_DIR, "symbolscollector/generated_file.h"}, "void function();", {}}}; filePathId({TESTDATA_DIR, "symbolscollector/generated_file.h"}),
"void function();",
{}}};
collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/unsaved.cpp"), {"cc"}); collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/unsaved.cpp"), {"cc"});
collector.setUnsavedFiles(std::move(unsaved)); collector.setUnsavedFiles(std::move(unsaved));