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

View File

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

View File

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

View File

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

View File

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

View File

@@ -53,7 +53,7 @@ void GeneratedFiles::update(const V2::FileContainers &fileContainers)
V2::FileContainers unionFileContainers;
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;
};
@@ -69,10 +69,7 @@ void GeneratedFiles::update(const V2::FileContainers &fileContainers)
class Compare {
public:
bool operator()(const FilePath &first, const FilePath &second)
{
return first < second;
}
bool operator()(const FilePath &first, const FilePath &second) { return first < second; }
bool operator()(const V2::FileContainer &first, const V2::FileContainer &second)
{
return first.filePath < second.filePath;
@@ -116,4 +113,16 @@ const V2::FileContainers &GeneratedFiles::fileContainers() const
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

View File

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

View File

@@ -38,6 +38,7 @@ public:
virtual bool isValid() const = 0;
virtual const V2::FileContainers &fileContainers() const = 0;
virtual FilePathIds filePathIds() const = 0;
protected:
~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
{
try {
Sqlite::DeferredTransaction transaction{database};
ProjectPartId projectPartId;
auto optionalProjectPartId = fetchProjectPartIdStatement.template value<ProjectPartId>(
projectPartName);
if (optionalProjectPartId) {
projectPartId = *optionalProjectPartId;
} else {
insertProjectPartNameStatement.write(projectPartName);
projectPartId = static_cast<int>(database.lastInsertedRowId());
}
ProjectPartId projectPartId = fetchProjectPartIdUnguarded(projectPartName);
transaction.commit();
return projectPartId;
} catch (const Sqlite::StatementIsBusy &) {
return fetchProjectPartId(projectPartName);
}
@@ -330,6 +337,23 @@ public:
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:
Sqlite::ImmediateNonThrowingDestructorTransaction transaction;
Database &database;
@@ -383,5 +407,7 @@ public:
"SELECT projectPchBuildTime FROM precompiledHeaders WHERE projectPartId = ?", database};
WriteStatement resetDependentIndexingTimeStampsStatement{
"UPDATE fileStatuses SET indexingTimeStamp = NULL WHERE sourceId = ?", database};
mutable ReadStatement fetchAllProjectPartNamesAndIdsStatement{
"SELECT projectPartName, projectPartId FROM projectParts", database};
};
} // namespace ClangBackEnd

View File

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

View File

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

View File

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

View File

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

View File

@@ -32,6 +32,8 @@
#include <filecontainerv2.h>
#include <utils/algorithm.h>
#include <QObject>
namespace ProjectExplorer {
@@ -46,7 +48,8 @@ namespace ClangPchManager {
namespace Internal {
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);
}
@@ -83,9 +86,13 @@ public:
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)
@@ -98,6 +105,14 @@ protected:
const Utils::FilePath &,
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)
abstractEditorUpdated(target.toString(), {});
}
@@ -105,7 +120,8 @@ protected:
private:
void connectToCppModelManager()
{
ProjectUpdaterType::updateGeneratedFiles(Internal::createGeneratedFiles());
ProjectUpdaterType::updateGeneratedFiles(
Internal::createGeneratedFiles(ProjectUpdaterType::m_filePathCache));
QObject::connect(Internal::cppModelManager(),
&CppTools::CppModelManager::projectPartsUpdated,

View File

@@ -82,10 +82,9 @@ void ClangQueryProjectsFindFilter::requestSourceRangesAndDiagnostics(const QStri
{
const QString filePath = temporaryFile.fileName();
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message(queryText,
{ClangBackEnd::FilePath(filePath),
exampleContent,
{"cc", "-std=c++1z", toNative(filePath)}});
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message(
queryText,
{ClangBackEnd::FilePath(filePath), 1, exampleContent, {"cc", "-std=c++1z", toNative(filePath)}});
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)) {
sources.emplace_back(ClangBackEnd::FilePath(projectFile.path),
-1,
"",
createCommandLine(projectPart.data(),
projectFile.path,
projectFile.kind));
createCommandLine(projectPart.data(), projectFile.path, projectFile.kind));
}
}

View File

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

View File

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

View File

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

View File

@@ -41,6 +41,7 @@
#include <utils/smallstring.h>
#include <QApplication>
#include <QDirIterator>
#include <algorithm>
@@ -50,12 +51,14 @@ PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
PchTaskGeneratorInterface &pchTaskGenerator,
ProjectPartsManagerInterface &projectParts,
GeneratedFilesInterface &generatedFiles,
BuildDependenciesStorageInterface &buildDependenciesStorage)
BuildDependenciesStorageInterface &buildDependenciesStorage,
FilePathCachingInterface &filePathCache)
: m_fileSystemWatcher(fileSystemWatcher)
, m_pchTaskGenerator(pchTaskGenerator)
, m_projectPartsManager(projectParts)
, m_generatedFiles(generatedFiles)
, m_buildDependenciesStorage(buildDependenciesStorage)
, m_filePathCache(filePathCache)
{
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
void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message)
{
m_filePathCache.populateIfEmpty();
m_filePathCache.addFilePaths(gatherPathsInIncludePaths(message.projectsParts));
m_toolChainsArgumentsCache.update(message.projectsParts, message.toolChainArguments);
auto upToDateProjectParts = m_projectPartsManager.update(message.takeProjectsParts());

View File

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

View File

@@ -56,27 +56,6 @@ namespace {
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)
{
switch (sourceEntry.sourceType) {
@@ -109,16 +88,6 @@ FilePathIds existingSources(const FilePathIds &sources, const FilePathIds &gener
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
ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts)
@@ -175,7 +144,7 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep
auto systemSplit = updateSystemProjectParts.end();
FilePathIds generatedFiles = toFilePathIds(m_generatedFiles.fileContainers(), m_filePathCache);
FilePathIds generatedFiles = m_generatedFiles.filePathIds();
std::vector<IdPaths> watchedIdPaths;
watchedIdPaths.reserve(upToDateProjectParts.size() * 4);

View File

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

View File

@@ -57,7 +57,7 @@ public:
, m_database(database)
{}
void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks)
void addOrUpdateTasks(std::vector<SymbolIndexerTask> &&tasks) override
{
auto merge = [] (SymbolIndexerTask &&first, SymbolIndexerTask &&second) {
first.callable = std::move(second.callable);
@@ -71,7 +71,7 @@ public:
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) {
return std::binary_search(projectPartIds.begin(), projectPartIds.end(), task.projectPartId);
@@ -91,7 +91,7 @@ public:
return m_tasks;
}
void processEntries()
void processEntries() override
{
auto slotUsage = m_symbolIndexerScheduler.slotUsage();
uint taskCount = slotUsage.free;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -79,6 +79,7 @@ protected:
NiceMock<MockFilePathStorage> mockStorage{mockDatabase};
Cache cache{mockStorage};
NiceMock<MockFilePathStorage> mockStorageFilled{mockDatabase};
Cache cacheNotFilled{mockStorageFilled};
};
TEST_F(FilePathCache, FilePathIdWithOutAnyEntryCallDirectoryId)
@@ -439,4 +440,51 @@ TEST_F(FilePathCache, UseTransactionIfAddingFilesOnlyInAddFilePathsCalls)
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

View File

@@ -35,12 +35,12 @@ using ClangBackEnd::V2::FileContainers;
class GeneratedFiles : public testing::Test
{
protected:
FileContainer file1{"/file1", "content1"};
FileContainer file1b{"/file1", "content1b"};
FileContainer file2{"/file2", "content2"};
FileContainer file2b{"/file2", "content2b"};
FileContainer file3{"/file3", "content3"};
FileContainer file4{"/file4", "content4"};
FileContainer file1{"/file1", 1, "content1"};
FileContainer file1b{"/file1", 1, "content1b"};
FileContainer file2{"/file2", 2, "content2"};
FileContainer file2b{"/file2", 2, "content2b"};
FileContainer file3{"/file3", 3, "content3"};
FileContainer file4{"/file4", 4, "content4"};
ClangBackEnd::GeneratedFiles generatedFiles;
};
@@ -76,7 +76,7 @@ TEST_F(GeneratedFiles, IsValidForNoGeneratedFiles)
TEST_F(GeneratedFiles, IsNotValidIfFilesWithNotContentExists)
{
generatedFiles.update({{"/file2", ""}});
generatedFiles.update({{"/file2", 2, ""}});
ASSERT_FALSE(generatedFiles.isValid());
}
@@ -86,4 +86,15 @@ TEST_F(GeneratedFiles, IsValidIfAllFilesHasContent)
generatedFiles.update({file1, file2, file3, file4});
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::PathString &text, ::std::ostream *os);
} // namespace ProjectExplorer
} // namespace Utils
namespace ClangBackEnd {
class SourceLocationEntry;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -27,6 +27,7 @@
#include "mockbuilddependenciesstorage.h"
#include "mockclangpathwatcher.h"
#include "mockfilepathcaching.h"
#include "mockgeneratedfiles.h"
#include "mockpchmanagerclient.h"
#include "mockpchtaskgenerator.h"
@@ -77,11 +78,13 @@ protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
ClangBackEnd::FilePathCaching filePathCache{database};
NiceMock<MockFilePathCaching> mockFilePathCache;
ClangBackEnd::PchManagerServer server{mockClangPathWatcher,
mockPchTaskGenerator,
mockProjectPartsManager,
mockGeneratedFiles,
mockBuildDependenciesStorage};
mockBuildDependenciesStorage,
mockFilePathCache};
NiceMock<MockPchManagerClient> mockPchManagerClient;
ClangBackEnd::ProjectPartId projectPartId1{1};
ClangBackEnd::ProjectPartId projectPartId2{2};
@@ -98,7 +101,7 @@ protected:
projectPartId1,
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{TESTDATA_DIR "/symbolscollector/include", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header1Path)},
{id(main1Path)},
@@ -110,7 +113,7 @@ protected:
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{{TESTDATA_DIR "/builddependencycollector", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header2Path)},
{id(main2Path)},
Utils::Language::C,
@@ -165,7 +168,7 @@ protected:
std::vector<ProjectPartContainer> projectParts2{projectPart2};
std::vector<ProjectPartContainer> projectParts3{projectPart3};
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{
Utils::clone(projectParts), {"toolChainArgument"}};
ClangBackEnd::RemoveProjectPartsMessage removeProjectPartsMessage{
@@ -226,7 +229,8 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier)
mockPchTaskGenerator,
mockProjectPartsManager,
mockGeneratedFiles,
mockBuildDependenciesStorage};
mockBuildDependenciesStorage,
filePathCache};
}
TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds)
@@ -419,4 +423,20 @@ TEST_F(PchManagerServer, SentUpToDateProjectPartIdsToClient)
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

View File

@@ -29,11 +29,13 @@
#include <builddependenciesstorage.h>
#include <projectpartsstorage.h>
#include <projectpartstoragestructs.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
#include <symbolstorage.h>
namespace {
using ClangBackEnd::FilePathId;
@@ -107,6 +109,7 @@ protected:
MockSqliteReadStatement &fetchProjectPrecompiledHeaderPathStatement = storage.fetchProjectPrecompiledHeaderBuildTimeStatement;
MockSqliteReadStatement &fetchProjectPrecompiledHeaderBuildTimeStatement = storage.fetchProjectPrecompiledHeaderBuildTimeStatement;
MockSqliteWriteStatement &resetDependentIndexingTimeStampsStatement = storage.resetDependentIndexingTimeStampsStatement;
MockSqliteReadStatement &fetchAllProjectPartNamesAndIdsStatement = storage.fetchAllProjectPartNamesAndIdsStatement;
IncludeSearchPaths systemIncludeSearchPaths{{"/includes", 1, IncludeSearchPathType::BuiltIn},
{"/other/includes", 2, IncludeSearchPathType::System}};
IncludeSearchPaths projectIncludeSearchPaths{{"/project/includes", 1, IncludeSearchPathType::User},
@@ -124,6 +127,7 @@ protected:
Utils::Language::Cxx,
Utils::LanguageVersion::CXX11,
Utils::LanguageExtension::None};
ClangBackEnd::Internal::ProjectPartNameIds projectPartNameIds{{"projectPartName", 2}};
};
TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithNonExistingProjectPartName)
@@ -139,6 +143,17 @@ TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithNonExistingProjectPartName)
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)
{
InSequence s;
@@ -153,6 +168,18 @@ TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithExistingProjectPart)
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)
{
InSequence s;
@@ -184,6 +211,18 @@ TEST_F(ProjectPartsStorage, FetchProjectIdWithNonExistingProjectPartName)
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)
{
InSequence s;
@@ -211,6 +250,17 @@ TEST_F(ProjectPartsStorage, FetchProjectIdWithExistingProjectPartName)
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)
{
InSequence s;
@@ -418,6 +468,7 @@ TEST_F(ProjectPartsStorage, FetchProjectPartArtefactBySourceIdCallsValueInStatem
storage.fetchProjectPartArtefact(FilePathId{1});
}
TEST_F(ProjectPartsStorage, FetchProjectPartArtefactBySourceIdReturnArtefact)
{
EXPECT_CALL(getProjectPartArtefactsBySourceId, valueReturnProjectPartArtefact(1))
@@ -495,6 +546,34 @@ TEST_F(ProjectPartsStorage, ResetDependentIndexingTimeStampsIsBusy)
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
{
using Storage = ClangBackEnd::ProjectPartsStorage<Sqlite::Database>;
@@ -530,6 +609,15 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectPartId)
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)
{
projectPart1.projectPartId = storage.fetchProjectPartId("project1");
@@ -563,4 +651,16 @@ TEST_F(ProjectPartsStorageSlow, ResetDependentIndexingTimeStamps)
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

View File

@@ -66,10 +66,11 @@ using testing::NiceMock;
using testing::AnyNumber;
using ClangBackEnd::CompilerMacro;
using ClangBackEnd::FilePath;
using ClangBackEnd::IncludeSearchPath;
using ClangBackEnd::IncludeSearchPathType;
using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::V2::FileContainer;
using CppTools::CompilerOptionsBuilder;
using ProjectExplorer::HeaderPath;
@@ -182,9 +183,18 @@ protected:
CppTools::ProjectPart nonBuildingProjectPart;
ProjectPartContainer expectedContainer;
ProjectPartContainer expectedContainer2;
FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}};
FileContainer generatedFile2{{"/path/to2", "header1.h"}, "content", {}};
FileContainer generatedFile3{{"/path/to", "header2.h"}, "content", {}};
FileContainer generatedFile{{"/path/to", "header1.h"},
filePathCache.filePathId(FilePath{"/path/to", "header1.h"}),
"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)
@@ -271,6 +281,7 @@ TEST_F(ProjectUpdater, CallPrecompiledHeaderRemovedInPchManagerProjectUpdater)
TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer)
{
updater.setExcludedPaths({"/path/to/header1.h"});
updater.fetchProjectPartIds({&projectPart});
auto container = updater.toProjectPartContainer(&projectPart);
@@ -279,21 +290,23 @@ TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer)
TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainersHaveSameSizeLikeProjectParts)
{
updater.fetchProjectPartIds({&projectPart, &nonBuildingProjectPart});
auto containers = updater.toProjectPartContainers(
{&projectPart, &projectPart, &nonBuildingProjectPart});
ASSERT_THAT(containers, SizeIs(2));
}
TEST_F(ProjectUpdater, CallStorageInsideTransaction)
TEST_F(ProjectUpdater, ProjectPartIdsPrefetchingInsideTransaction)
{
InSequence s;
CppTools::ProjectPart projectPart;
projectPart.project = &project;
projectPart.displayName = "project";
Utils::SmallString projectPartName = projectPart.id();
MockSqliteTransactionBackend mockSqliteTransactionBackend;
MockProjectPartsStorage mockProjectPartsStorage;
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
ON_CALL(mockProjectPartsStorage, transactionBackend())
.WillByDefault(ReturnRef(mockSqliteTransactionBackend));
ClangPchManager::ClangIndexingSettingsManager settingsManager;
@@ -302,9 +315,11 @@ TEST_F(ProjectUpdater, CallStorageInsideTransaction)
mockProjectPartsStorage,
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)
@@ -476,7 +491,8 @@ TEST_F(ProjectUpdater, AddProjectFilesToFilePathCache)
NiceMock<MockFilePathCaching> mockFilePathCaching;
ClangPchManager::ProjectUpdater updater{mockPchManagerServer,
mockFilePathCaching,
projectPartsStorage};
projectPartsStorage,
settingsManager};
EXPECT_CALL(mockFilePathCaching,
addFilePaths(UnorderedElementsAre(Eq(headerPaths[0]),
@@ -487,6 +503,39 @@ TEST_F(ProjectUpdater, AddProjectFilesToFilePathCache)
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

View File

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

View File

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

View File

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

View File

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

View File

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