Clang: Improve project part updating

The project part ids are now already created very early in the database.
This removes some checks because we can assume that an id already exists.
The project part are now completely persistent, so we can read them from
the database and compare them with new generated from a new creator
session. This should help to not recreate the same PCH again and again.

Task-number: QTCREATORBUG-21151
Change-Id: Iced818ff9f7431eaed3e37978087cc0a43b9afda
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2019-03-13 15:09:30 +01:00
parent 7249427749
commit 6effa1822b
111 changed files with 2657 additions and 1803 deletions

View File

@@ -38,7 +38,7 @@ namespace ClangBackEnd {
class WatcherEntry
{
public:
int id;
ProjectPartId id;
FilePathId pathId;
friend bool operator==(WatcherEntry first, WatcherEntry second)
@@ -69,13 +69,6 @@ public:
using WatcherEntries = std::vector<WatcherEntry>;
using IdCache = StringCache<Utils::SmallString,
Utils::SmallStringView,
int,
NonLockingMutex,
decltype(&Utils::compare),
Utils::compare>;
template <typename FileSystemWatcher,
typename Timer>
class CLANGSUPPORT_GCCEXPORT ClangPathWatcher : public ClangPathWatcherInterface
@@ -109,9 +102,9 @@ public:
removeUnusedEntries(entriesAndIds.first, entriesAndIds.second);
}
void removeIds(const Utils::SmallStringVector &ids) override
void removeIds(const ProjectPartIds &ids) override
{
auto removedEntries = removeIdsFromWatchedEntries(convertToIdNumbers(ids));
auto removedEntries = removeIdsFromWatchedEntries(ids);
auto filteredPaths = filterNotWatchedPaths(removedEntries);
@@ -124,7 +117,6 @@ public:
m_notifier = notifier;
}
unittest_public:
static std::vector<uint> idsFromIdPaths(const std::vector<IdPaths> &idPaths)
{
std::vector<uint> ids;
@@ -144,15 +136,6 @@ unittest_public:
return ids;
}
std::vector<int> convertToIdNumbers(const Utils::SmallStringVector &ids)
{
std::vector<int> idNumbers = m_idCache.stringIds(ids);
std::sort(idNumbers.begin(), idNumbers.end());
return idNumbers;
}
std::size_t sizeOfIdPaths(const std::vector<IdPaths> &idPaths)
{
auto sumSize = [] (std::size_t size, const IdPaths &idPath) {
@@ -162,20 +145,19 @@ unittest_public:
return std::accumulate(idPaths.begin(), idPaths.end(), std::size_t(0), sumSize);
}
std::pair<WatcherEntries, std::vector<int>>
convertIdPathsToWatcherEntriesAndIds(const std::vector<IdPaths> &idPaths)
std::pair<WatcherEntries, ProjectPartIds> convertIdPathsToWatcherEntriesAndIds(
const std::vector<IdPaths> &idPaths)
{
WatcherEntries entries;
entries.reserve(sizeOfIdPaths(idPaths));
std::vector<int> ids;
ProjectPartIds ids;
ids.reserve(ids.size());
auto outputIterator = std::back_inserter(entries);
for (const IdPaths &idPath : idPaths)
{
int id = m_idCache.stringId(idPath.id);
ProjectPartId id = idPath.id;
ids.push_back(id);
@@ -203,8 +185,7 @@ unittest_public:
m_fileSystemWatcher.addPaths(convertWatcherEntriesToQStringList(filteredPaths));
}
void removeUnusedEntries(const WatcherEntries &entries,
const std::vector<int> &ids)
void removeUnusedEntries(const WatcherEntries &entries, const ProjectPartIds &ids)
{
auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids);
@@ -286,9 +267,8 @@ unittest_public:
return notAnymoreWatchedEntries;
}
WatcherEntries notAnymoreWatchedEntriesWithIds(
const WatcherEntries &newEntries,
const std::vector<int> &ids) const
WatcherEntries notAnymoreWatchedEntriesWithIds(const WatcherEntries &newEntries,
const ProjectPartIds &ids) const
{
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
@@ -345,16 +325,13 @@ unittest_public:
return m_watchedEntries;
}
WatcherEntries removeIdsFromWatchedEntries(const std::vector<int> &ids)
WatcherEntries removeIdsFromWatchedEntries(const ProjectPartIds &ids)
{
auto keep = [&] (WatcherEntry entry) {
auto keep = [&](WatcherEntry entry) {
return !std::binary_search(ids.begin(), ids.end(), entry.id);
};
auto found = std::stable_partition(m_watchedEntries.begin(),
m_watchedEntries.end(),
keep);
auto found = std::stable_partition(m_watchedEntries.begin(), m_watchedEntries.end(), keep);
WatcherEntries removedEntries(found, m_watchedEntries.end());
@@ -410,22 +387,20 @@ unittest_public:
return watchedFilePathIds;
}
Utils::SmallStringVector idsForWatcherEntries(const WatcherEntries &foundEntries)
ProjectPartIds idsForWatcherEntries(const WatcherEntries &foundEntries)
{
Utils::SmallStringVector ids;
ProjectPartIds ids;
ids.reserve(foundEntries.size());
std::transform(foundEntries.begin(),
foundEntries.end(),
std::back_inserter(ids),
[&] (WatcherEntry entry) {
return Utils::SmallString(m_idCache.string(entry.id));
});
[&](WatcherEntry entry) { return entry.id; });
return ids;
}
Utils::SmallStringVector uniqueIds(Utils::SmallStringVector &&ids)
ProjectPartIds uniqueIds(ProjectPartIds &&ids)
{
std::sort(ids.begin(), ids.end());
auto newEnd = std::unique(ids.begin(), ids.end());
@@ -439,7 +414,7 @@ unittest_public:
if (m_notifier) {
WatcherEntries foundEntries = watchedEntriesForPaths(std::move(filePathIds));
Utils::SmallStringVector changedIds = idsForWatcherEntries(foundEntries);
ProjectPartIds changedIds = idsForWatcherEntries(foundEntries);
m_notifier->pathsWithIdsChanged(uniqueIds(std::move(changedIds)));
m_notifier->pathsChanged(watchedPaths(filePathIds));
@@ -451,13 +426,7 @@ unittest_public:
return m_pathCache;
}
IdCache &idCache()
{
return m_idCache;
}
private:
IdCache m_idCache;
WatcherEntries m_watchedEntries;
ChangedFilePathCompressor<Timer> m_changedFilePathCompressor;
FileSystemWatcher m_fileSystemWatcher;

View File

@@ -41,7 +41,7 @@ public:
ClangPathWatcherInterface &operator=(const ClangPathWatcherInterface &) = delete;
virtual void updateIdPaths(const std::vector<IdPaths> &idPaths) = 0;
virtual void removeIds(const Utils::SmallStringVector &ids) = 0;
virtual void removeIds(const ProjectPartIds &ids) = 0;
virtual void setNotifier(ClangPathWatcherNotifier *notifier) = 0;

View File

@@ -28,6 +28,7 @@
#include "clangsupport_global.h"
#include <filepathid.h>
#include <projectpartid.h>
#include <utils/smallstringvector.h>
@@ -40,7 +41,7 @@ public:
ClangPathWatcherNotifier(const ClangPathWatcherNotifier &) = delete;
ClangPathWatcherNotifier &operator=(const ClangPathWatcherNotifier &) = delete;
virtual void pathsWithIdsChanged(const Utils::SmallStringVector &ids) = 0;
virtual void pathsWithIdsChanged(const ProjectPartIds &ids) = 0;
virtual void pathsChanged(const FilePathIds &filePathIds) = 0;
protected:

View File

@@ -52,7 +52,6 @@ SOURCES += \
$$PWD/refactoringserverproxy.cpp \
$$PWD/referencesmessage.cpp \
$$PWD/unsavedfilesupdatedmessage.cpp \
$$PWD/removeprojectpartsmessage.cpp \
$$PWD/requestannotationsmessage.cpp \
$$PWD/requestfollowsymbolmessage.cpp \
$$PWD/requestreferencesmessage.cpp \
@@ -87,6 +86,7 @@ SOURCES += \
$$PWD/updategeneratedfilesmessage.cpp \
$$PWD/removegeneratedfilesmessage.cpp \
$$PWD/generatedfiles.cpp \
$$PWD/projectpartartefact.cpp \
$$PWD/projectpartcontainer.cpp
HEADERS += \
@@ -107,8 +107,12 @@ HEADERS += \
$$PWD/clangrefactoringmessages.h \
$$PWD/clangrefactoringservermessages.h \
$$PWD/alivemessage.h \
$$PWD/clangsupportexceptions.h \
$$PWD/completionsmessage.h \
$$PWD/executeinloop.h \
$$PWD/projectpartid.h \
$$PWD/projectpartsstorage.h \
$$PWD/projectpartsstorageinterface.h \
$$PWD/requestcompletionsmessage.h \
$$PWD/echomessage.h \
$$PWD/endmessage.h \
@@ -208,6 +212,7 @@ HEADERS += \
$$PWD/progresscounter.h \
$$PWD/includesearchpath.h \
$$PWD/commandlinebuilder.h \
$$PWD/projectpartartefact.h \
$$PWD/projectpartcontainer.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,6 +23,8 @@
**
****************************************************************************/
#pragma once
#include <sqliteexception.h>
namespace ClangBackEnd {
@@ -30,11 +32,16 @@ namespace ClangBackEnd {
class ProjectPartArtefactParseError : public Sqlite::Exception
{
public:
ProjectPartArtefactParseError(const char *whatErrorHasHappen,
Utils::SmallString &&errorMessage)
ProjectPartArtefactParseError(const char *whatErrorHasHappen, Utils::SmallString &&errorMessage)
: Exception(whatErrorHasHappen, std::move(errorMessage))
{
}
{}
};
}
class ProjectPartDoesNotExists : public Sqlite::Exception
{
public:
ProjectPartDoesNotExists(const char *whatErrorHasHappen, Utils::SmallString &&errorMessage)
: Exception(whatErrorHasHappen, std::move(errorMessage))
{}
};
} // namespace ClangBackEnd

View File

@@ -95,6 +95,8 @@ public:
m_slashIndex(std::ptrdiff_t(directory.size()))
{}
bool isValid() const { return size() > 0 && m_slashIndex >= 0; }
Utils::SmallStringView directory() const noexcept
{
return mid(0, std::size_t(std::max(std::ptrdiff_t(0), m_slashIndex)));

View File

@@ -40,6 +40,8 @@ class FilePathId
public:
constexpr FilePathId() = default;
FilePathId(const char *) = delete;
FilePathId(int filePathId)
: filePathId(filePathId)
{}

View File

@@ -25,8 +25,7 @@
#pragma once
#include <utils/smallstring.h>
#include "projectpartid.h"
#include "filepathid.h"
namespace ClangBackEnd {
@@ -34,7 +33,7 @@ namespace ClangBackEnd {
class IdPaths
{
public:
Utils::SmallString id;
ProjectPartId id;
FilePathIds filePathIds;
friend bool operator==(const IdPaths &first, const IdPaths &second)

View File

@@ -25,7 +25,9 @@
#pragma once
#include "projectpartartefactexception.h"
#include "clangsupport_global.h"
#include "clangsupportexceptions.h"
#include "projectpartid.h"
#include <utils/cpplanguage_details.h>
#include <utils/smallstringvector.h>
@@ -38,9 +40,28 @@ QT_FORWARD_DECLARE_STRUCT(QJsonParseError)
namespace ClangBackEnd {
class ProjectPartArtefact
class CLANGSUPPORT_EXPORT ProjectPartArtefact
{
public:
ProjectPartArtefact() = default;
ProjectPartArtefact(ProjectPartId projectPartId,
Utils::SmallStringVector &&toolChainArguments,
CompilerMacros &&compilerMacros,
IncludeSearchPaths &&systemIncludeSearchPaths,
IncludeSearchPaths &&projectIncludeSearchPaths,
Utils::Language language,
Utils::LanguageVersion languageVersion,
Utils::LanguageExtension languageExtension)
: projectPartId(projectPartId)
, toolChainArguments(std::move(toolChainArguments))
, compilerMacros(std::move(compilerMacros))
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
, language(language)
, languageVersion(languageVersion)
, languageExtension(languageExtension)
{}
ProjectPartArtefact(Utils::SmallStringView compilerArgumentsText,
Utils::SmallStringView compilerMacrosText,
Utils::SmallStringView systemIncludeSearchPathsText,
@@ -49,11 +70,11 @@ public:
int language,
int languageVersion,
int languageExtension)
: toolChainArguments(toStringVector(compilerArgumentsText))
: projectPartId(projectPartId)
, toolChainArguments(toStringVector(compilerArgumentsText))
, compilerMacros(toCompilerMacros(compilerMacrosText))
, systemIncludeSearchPaths(toIncludeSearchPaths(systemIncludeSearchPathsText))
, projectIncludeSearchPaths(toIncludeSearchPaths(projectIncludeSearchPathsText))
, projectPartId(projectPartId)
, language(static_cast<Utils::Language>(language))
, languageVersion(static_cast<Utils::LanguageVersion>(languageVersion))
, languageExtension(static_cast<Utils::LanguageExtension>(languageExtension))
@@ -67,11 +88,11 @@ public:
Utils::Language language,
Utils::LanguageVersion languageVersion,
Utils::LanguageExtension languageExtension)
: toolChainArguments(toStringVector(compilerArgumentsText))
: projectPartId(projectPartId)
, toolChainArguments(toStringVector(compilerArgumentsText))
, compilerMacros(toCompilerMacros(compilerMacrosText))
, systemIncludeSearchPaths(toIncludeSearchPaths(systemIncludeSearchPathsText))
, projectIncludeSearchPaths(toIncludeSearchPaths(projectIncludeSearchPathsText))
, projectPartId(projectPartId)
, language(language)
, languageVersion(languageVersion)
, languageExtension(languageExtension)
@@ -87,11 +108,11 @@ public:
friend bool operator==(const ProjectPartArtefact &first, const ProjectPartArtefact &second);
public:
ProjectPartId projectPartId;
Utils::SmallStringVector toolChainArguments;
CompilerMacros compilerMacros;
IncludeSearchPaths systemIncludeSearchPaths;
IncludeSearchPaths projectIncludeSearchPaths;
int projectPartId = -1;
Utils::Language language = Utils::Language::Cxx;
Utils::LanguageVersion languageVersion = Utils::LanguageVersion::CXX98;
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None;

View File

@@ -29,12 +29,9 @@ namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const ProjectPartContainer &container)
{
debug.nospace() << "ProjectPartContainer("
<< container.projectPartId << ","
<< container.toolChainArguments << ", "
<< container.headerPathIds << ", "
<< container.sourcePathIds
<< ")";
debug.nospace() << "ProjectPartContainer(" << container.projectPartId.projectPathId << ","
<< container.toolChainArguments << ", " << container.headerPathIds << ", "
<< container.sourcePathIds << ")";
return debug;
}

View File

@@ -30,19 +30,21 @@
#include "compilermacro.h"
#include "filepathid.h"
#include "includesearchpath.h"
#include "projectpartartefact.h"
#include "projectpartid.h"
#include <utils/cpplanguage_details.h>
#include <utils/smallstringio.h>
namespace ClangBackEnd {
class ProjectPartContainer
class ProjectPartContainer : public ProjectPartArtefact
{
using uchar = unsigned char;
public:
ProjectPartContainer() = default;
ProjectPartContainer(Utils::SmallString &&projectPartId,
Utils::SmallStringVector &&arguments,
ProjectPartContainer(ProjectPartId projectPartId,
Utils::SmallStringVector &&toolChainArguments,
CompilerMacros &&compilerMacros,
IncludeSearchPaths &&systemIncludeSearchPaths,
IncludeSearchPaths &&projectIncludeSearchPaths,
@@ -51,18 +53,36 @@ public:
Utils::Language language,
Utils::LanguageVersion languageVersion,
Utils::LanguageExtension languageExtension)
: projectPartId(std::move(projectPartId))
, toolChainArguments(std::move(arguments))
, compilerMacros(std::move(compilerMacros))
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
: ProjectPartArtefact(projectPartId,
std::move(toolChainArguments),
std::move(compilerMacros),
std::move(systemIncludeSearchPaths),
std::move(projectIncludeSearchPaths),
language,
languageVersion,
languageExtension)
, headerPathIds(std::move(headerPathIds))
, sourcePathIds(std::move(sourcePathIds))
, language(language)
, languageVersion(languageVersion)
, languageExtension(languageExtension)
{
}
{}
ProjectPartContainer(Utils::SmallStringView compilerArgumentsText,
Utils::SmallStringView compilerMacrosText,
Utils::SmallStringView systemIncludeSearchPathsText,
Utils::SmallStringView projectIncludeSearchPathsText,
int projectPartId,
int language,
int languageVersion,
int languageExtension)
: ProjectPartArtefact(compilerArgumentsText,
compilerMacrosText,
systemIncludeSearchPathsText,
projectIncludeSearchPathsText,
projectPartId,
language,
languageVersion,
languageExtension)
{}
friend QDataStream &operator<<(QDataStream &out, const ProjectPartContainer &container)
{
@@ -146,20 +166,14 @@ public:
}
public:
Utils::SmallString projectPartId;
Utils::SmallStringVector toolChainArguments;
CompilerMacros compilerMacros;
IncludeSearchPaths systemIncludeSearchPaths;
IncludeSearchPaths projectIncludeSearchPaths;
FilePathIds headerPathIds;
FilePathIds sourcePathIds;
Utils::Language language = Utils::Language::Cxx;
Utils::LanguageVersion languageVersion = Utils::LanguageVersion::CXX98;
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None;
bool updateIsDeferred = false;
};
using ProjectPartContainerReference = std::reference_wrapper<ProjectPartContainer>;
using ProjectPartContainers = std::vector<ProjectPartContainer>;
using ProjectPartContainerReferences = std::vector<ProjectPartContainerReference>;
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const ProjectPartContainer &container);

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -23,16 +23,55 @@
**
****************************************************************************/
#include "removeprojectpartsmessage.h"
#pragma once
#include <QDataStream>
namespace ClangBackEnd {
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RemoveProjectPartsMessage &message)
class ProjectPartId
{
debug.nospace() << "RemoveProjectPartsMessage("
<< message.projectsPartIds << ")";
public:
constexpr ProjectPartId() = default;
return debug;
}
ProjectPartId(const char *) = delete;
ProjectPartId(int projectPathId)
: projectPathId(projectPathId)
{}
bool isValid() const { return projectPathId >= 0; }
friend bool operator==(ProjectPartId first, ProjectPartId second)
{
return first.isValid() && first.projectPathId == second.projectPathId;
}
friend bool operator!=(ProjectPartId first, ProjectPartId second) { return !(first == second); }
friend bool operator<(ProjectPartId first, ProjectPartId second)
{
return first.projectPathId < second.projectPathId;
}
friend QDataStream &operator<<(QDataStream &out, const ProjectPartId &projectPathId)
{
out << projectPathId.projectPathId;
return out;
}
friend QDataStream &operator>>(QDataStream &in, ProjectPartId &projectPathId)
{
in >> projectPathId.projectPathId;
return in;
}
public:
int projectPathId = -1;
};
using ProjectPartIds = std::vector<ProjectPartId>;
} // namespace ClangBackEnd

View File

@@ -29,8 +29,7 @@ namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const ProjectPartPch &projectPartPch)
{
debug.nospace() << "FileContainer("
<< projectPartPch.projectPartId << ", "
debug.nospace() << "FileContainer(" << projectPartPch.projectPartId.projectPathId << ", "
<< projectPartPch.pchPath << ")";
return debug;

View File

@@ -27,8 +27,8 @@
#include "clangsupport_global.h"
#include <utils/smallstringio.h>
#include <filepath.h>
#include <projectpartid.h>
namespace ClangBackEnd {
@@ -36,24 +36,28 @@ class ProjectPartPch
{
public:
ProjectPartPch() = default;
ProjectPartPch(Utils::SmallString &&projectPartId,
FilePath &&pchPath,
long long lastModified)
: projectPartId(std::move(projectPartId)),
pchPath(std::move(pchPath)),
lastModified(lastModified)
ProjectPartPch(ProjectPartId projectPartId, FilePath &&pchPath, long long lastModified)
: projectPartId(projectPartId)
, pchPath(std::move(pchPath))
, lastModified(lastModified)
{}
ProjectPartPch(Utils::SmallStringView pchPath,
long long lastModified)
: pchPath(FilePathView(pchPath)),
lastModified(lastModified)
ProjectPartPch(int projectPartId, Utils::SmallStringView pchPath, long long lastModified)
: projectPartId(projectPartId)
, pchPath(FilePathView(pchPath))
, lastModified(lastModified)
{}
bool isValid() const
{
return projectPartId.isValid() && pchPath.isValid() && lastModified >= 0;
}
friend QDataStream &operator<<(QDataStream &out, const ProjectPartPch &container)
{
out << container.projectPartId;
out << container.pchPath;
out << container.lastModified;
return out;
}
@@ -62,6 +66,7 @@ public:
{
in >> container.projectPartId;
in >> container.pchPath;
in >> container.lastModified;
return in;
}
@@ -79,7 +84,7 @@ public:
}
public:
Utils::SmallString projectPartId;
ProjectPartId projectPartId;
FilePath pchPath;
long long lastModified = -1;
};

View File

@@ -39,7 +39,7 @@ public:
ProjectPartPchProviderInterface &operator=(const ProjectPartPchProviderInterface &) = delete;
virtual Utils::optional<ClangBackEnd::ProjectPartPch> projectPartPch(
Utils::SmallStringView projectPartId) const = 0;
ClangBackEnd::ProjectPartId projectPartId) const = 0;
virtual const ClangBackEnd::ProjectPartPchs &projectPartPchs() const = 0;

View File

@@ -0,0 +1,336 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "clangsupportexceptions.h"
#include "projectpartsstorageinterface.h"
#include <sqliteexception.h>
#include <sqlitetransaction.h>
namespace ClangBackEnd {
template<typename Database = Sqlite::Database>
class ProjectPartsStorage final : public ProjectPartsStorageInterface
{
using ReadStatement = typename Database::ReadStatement;
using WriteStatement = typename Database::WriteStatement;
public:
ProjectPartsStorage(Database &database)
: transaction(database)
, database(database)
{
transaction.commit();
}
ProjectPartContainers fetchProjectParts() const override
{
try {
Sqlite::DeferredTransaction transaction{database};
auto values = fetchProjectPartsStatement.template values<ProjectPartContainer, 8>(4096);
transaction.commit();
return values;
} catch (const Sqlite::StatementIsBusy &) {
return fetchProjectParts();
}
}
FilePathIds fetchHeaders(ProjectPartId projectPartId) const
{
return fetchProjectPartsHeadersByIdStatement
.template values<FilePathId>(1024, projectPartId.projectPathId);
}
FilePathIds fetchSources(ProjectPartId projectPartId) const
{
return fetchProjectPartsSourcesByIdStatement
.template values<FilePathId>(1024, projectPartId.projectPathId);
}
ProjectPartContainers fetchProjectParts(const ProjectPartIds &projectPartIds) const override
{
try {
ProjectPartContainers projectParts;
projectParts.reserve(projectPartIds.size());
Sqlite::DeferredTransaction transaction{database};
for (ProjectPartId projectPartId : projectPartIds) {
auto value = fetchProjectPartByIdStatement.template value<ProjectPartContainer, 8>(
projectPartId.projectPathId);
if (value) {
value->headerPathIds = fetchHeaders(projectPartId);
value->sourcePathIds = fetchSources(projectPartId);
projectParts.push_back(*std::move(value));
}
}
transaction.commit();
return projectParts;
} catch (const Sqlite::StatementIsBusy &) {
return fetchProjectParts(projectPartIds);
}
}
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());
}
transaction.commit();
return projectPartId;
} catch (const Sqlite::StatementIsBusy &) {
return fetchProjectPartId(projectPartName);
}
}
Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const
{
try {
Sqlite::DeferredTransaction transaction{database};
auto optionalProjectPartName = fetchProjectPartNameStatement.template value<Utils::PathString>(
projectPartId.projectPathId);
transaction.commit();
if (optionalProjectPartName)
return *std::move(optionalProjectPartName);
} catch (const Sqlite::StatementIsBusy &) {
return fetchProjectPartName(projectPartId);
}
throwProjectPartDoesNotExists(projectPartId);
}
void insertHeaders(ProjectPartId projectPartId, const FilePathIds &headerPathIds)
{
deleteProjectPartsHeadersByIdStatement.write(projectPartId.projectPathId);
for (FilePathId headerPathId : headerPathIds) {
insertProjectPartsHeadersStatement.write(projectPartId.projectPathId,
headerPathId.filePathId);
}
}
void insertSources(ProjectPartId projectPartId, const FilePathIds &sourcePathIds)
{
deleteProjectPartsSourcesByIdStatement.write(projectPartId.projectPathId);
for (FilePathId sourcePathId : sourcePathIds) {
insertProjectPartsSourcesStatement.write(projectPartId.projectPathId,
sourcePathId.filePathId);
}
}
void updateProjectPart(ProjectPartId projectPartId,
const Utils::SmallStringVector &toolChainArguments,
const CompilerMacros &compilerMacros,
const IncludeSearchPaths &systemIncludeSearchPaths,
const IncludeSearchPaths &projectIncludeSearchPaths,
Utils::Language language,
Utils::LanguageVersion languageVersion,
Utils::LanguageExtension languageExtension) override
{
Utils::SmallString toolChainArgumentsAsJson = toJson(toolChainArguments);
Utils::SmallString compilerMacrosAsJson = toJson(compilerMacros);
Utils::SmallString systemIncludeSearchPathsAsJason = toJson(systemIncludeSearchPaths);
Utils::SmallString projectIncludeSearchPathsAsJason = toJson(projectIncludeSearchPaths);
updateProjectPartStatement.write(projectPartId.projectPathId,
toolChainArgumentsAsJson,
compilerMacrosAsJson,
systemIncludeSearchPathsAsJason,
projectIncludeSearchPathsAsJason,
static_cast<int>(language),
static_cast<int>(languageVersion),
static_cast<int>(languageExtension));
}
void updateProjectPart(const ProjectPartContainer &projectPart)
{
Utils::SmallString toolChainArgumentsAsJson = toJson(projectPart.toolChainArguments);
Utils::SmallString compilerMacrosAsJson = toJson(projectPart.compilerMacros);
Utils::SmallString systemIncludeSearchPathsAsJason = toJson(
projectPart.systemIncludeSearchPaths);
Utils::SmallString projectIncludeSearchPathsAsJason = toJson(
projectPart.projectIncludeSearchPaths);
updateProjectPartStatement.write(projectPart.projectPartId.projectPathId,
toolChainArgumentsAsJson,
compilerMacrosAsJson,
systemIncludeSearchPathsAsJason,
projectIncludeSearchPathsAsJason,
static_cast<int>(projectPart.language),
static_cast<int>(projectPart.languageVersion),
static_cast<int>(projectPart.languageExtension));
insertHeaders(projectPart.projectPartId, projectPart.headerPathIds);
insertSources(projectPart.projectPartId, projectPart.sourcePathIds);
}
void updateProjectParts(const ProjectPartContainers &projectParts) override
{
try {
Sqlite::ImmediateTransaction transaction{database};
for (const ProjectPartContainer &projectPart : projectParts)
updateProjectPart(projectPart);
transaction.commit();
} catch (const Sqlite::StatementIsBusy &) {
updateProjectParts(projectParts);
}
}
Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const override
{
ReadStatement &statement = getProjectPartArtefactsBySourceId;
return statement.template value<ProjectPartArtefact, 8>(sourceId.filePathId);
}
Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(ProjectPartId projectPartId) const override
{
ReadStatement &statement = getProjectPartArtefactsByProjectPartId;
return statement.template value<ProjectPartArtefact, 8>(projectPartId.projectPathId);
}
Sqlite::TransactionInterface &transactionBackend() override { return database; }
static Utils::SmallString toJson(const Utils::SmallStringVector &strings)
{
QJsonDocument document;
QJsonArray array;
std::transform(strings.begin(),
strings.end(),
std::back_inserter(array),
[](const auto &string) { return QJsonValue(string.data()); });
document.setArray(array);
return document.toJson(QJsonDocument::Compact);
}
static Utils::SmallString toJson(const CompilerMacros &compilerMacros)
{
QJsonDocument document;
QJsonArray array;
for (const CompilerMacro &macro : compilerMacros)
array.push_back(QJsonArray{{QString(macro.key), QString(macro.value), macro.index}});
document.setArray(array);
return document.toJson(QJsonDocument::Compact);
}
static Utils::SmallString toJson(const IncludeSearchPaths &includeSearchPaths)
{
QJsonDocument document;
QJsonArray array;
for (const IncludeSearchPath &path : includeSearchPaths)
array.push_back(QJsonArray{{path.path.data(), path.index, int(path.type)}});
document.setArray(array);
return document.toJson(QJsonDocument::Compact);
}
[[noreturn]] void throwProjectPartDoesNotExists(ProjectPartId projectPartId) const
{
throw ProjectPartDoesNotExists("Try to fetch non existing project part id: ",
Utils::SmallString::number(projectPartId.projectPathId));
}
public:
Sqlite::ImmediateNonThrowingDestructorTransaction transaction;
Database &database;
mutable ReadStatement fetchProjectPartIdStatement{
"SELECT projectPartId FROM projectParts WHERE projectPartName = ?", database};
mutable WriteStatement insertProjectPartNameStatement{
"INSERT INTO projectParts(projectPartName) VALUES (?)", database};
mutable ReadStatement fetchProjectPartNameStatement{
"SELECT projectPartName FROM projectParts WHERE projectPartId = ?", database};
mutable ReadStatement fetchProjectPartsStatement{
"SELECT toolChainArguments, compilerMacros, systemIncludeSearchPaths, "
"projectIncludeSearchPaths, projectPartId, language, languageVersion, languageExtension "
"FROM projectParts",
database};
mutable ReadStatement fetchProjectPartByIdStatement{
"SELECT toolChainArguments, compilerMacros, systemIncludeSearchPaths, "
"projectIncludeSearchPaths, projectPartId, language, languageVersion, languageExtension "
"FROM projectParts WHERE projectPartId = ?",
database};
WriteStatement updateProjectPartStatement{
"UPDATE projectParts SET toolChainArguments=?002, compilerMacros=?003, "
"systemIncludeSearchPaths=?004, projectIncludeSearchPaths=?005, language=?006, "
"languageVersion=?007, languageExtension=?008 WHERE projectPartId = ?001",
database};
mutable ReadStatement getProjectPartArtefactsBySourceId{
"SELECT toolChainArguments, compilerMacros, systemIncludeSearchPaths, "
"projectIncludeSearchPaths, projectPartId, language, languageVersion, languageExtension "
"FROM projectParts WHERE projectPartId = (SELECT "
"projectPartId FROM projectPartsFiles WHERE sourceId = ?)",
database};
mutable ReadStatement getProjectPartArtefactsByProjectPartId{
"SELECT toolChainArguments, compilerMacros, systemIncludeSearchPaths, "
"projectIncludeSearchPaths, projectPartId, language, languageVersion, languageExtension "
"FROM projectParts WHERE projectPartId = ?",
database};
WriteStatement deleteProjectPartsHeadersByIdStatement{
"DELETE FROM projectPartsHeaders WHERE projectPartId = ?", database};
WriteStatement deleteProjectPartsSourcesByIdStatement{
"DELETE FROM projectPartsSources WHERE projectPartId = ?", database};
WriteStatement insertProjectPartsHeadersStatement{
"INSERT INTO projectPartsHeaders(projectPartId, sourceId) VALUES (?,?)", database};
WriteStatement insertProjectPartsSourcesStatement{
"INSERT INTO projectPartsSources(projectPartId, sourceId) VALUES (?,?)", database};
mutable ReadStatement fetchProjectPartsHeadersByIdStatement{
"SELECT sourceId FROM projectPartsHeaders WHERE projectPartId = ?", database};
mutable ReadStatement fetchProjectPartsSourcesByIdStatement{
"SELECT sourceId FROM projectPartsSources WHERE projectPartId = ?", database};
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <projectpartcontainer.h>
#include <sqlitetransaction.h>
#include <utils/optional.h>
#include <utils/smallstringview.h>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
namespace ClangBackEnd {
class ProjectPartsStorageInterface
{
public:
ProjectPartsStorageInterface() = default;
ProjectPartsStorageInterface(const ProjectPartsStorageInterface &) = delete;
ProjectPartsStorageInterface &operator=(const ProjectPartsStorageInterface &) = delete;
virtual ProjectPartContainers fetchProjectParts() const = 0;
virtual ProjectPartContainers fetchProjectParts(const ProjectPartIds &projectPartIds) const = 0;
virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) const = 0;
virtual Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const = 0;
virtual void updateProjectPart(ProjectPartId projectPartId,
const Utils::SmallStringVector &commandLineArguments,
const CompilerMacros &compilerMacros,
const ClangBackEnd::IncludeSearchPaths &systemIncludeSearchPaths,
const ClangBackEnd::IncludeSearchPaths &projectIncludeSearchPaths,
Utils::Language language,
Utils::LanguageVersion languageVersion,
Utils::LanguageExtension languageExtension)
= 0;
virtual void updateProjectParts(const ProjectPartContainers &projectParts) = 0;
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const = 0;
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(
ProjectPartId projectPartId) const = 0;
virtual Sqlite::TransactionInterface &transactionBackend() = 0;
protected:
~ProjectPartsStorageInterface() = default;
};
} // namespace ClangBackEnd

View File

@@ -47,11 +47,13 @@ public:
createSourcesTable();
createDirectoriesTable();
createProjectPartsTable();
createProjectPartsSourcesTable();
createProjectPartsFilesTable();
createUsedMacrosTable();
createFileStatusesTable();
createSourceDependenciesTable();
createPrecompiledHeadersTable();
createProjectPartsHeadersTable();
createProjectPartsSourcesTable();
transaction.commit();
@@ -135,11 +137,11 @@ public:
table.initialize(database);
}
void createProjectPartsSourcesTable()
void createProjectPartsFilesTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("projectPartsSources");
table.setName("projectPartsFiles");
const Sqlite::Column &projectPartIdColumn = table.addColumn("projectPartId", Sqlite::ColumnType::Integer);
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
table.addColumn("sourceType", Sqlite::ColumnType::Integer);
@@ -203,6 +205,32 @@ public:
table.initialize(database);
}
void createProjectPartsHeadersTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("projectPartsHeaders");
const Sqlite::Column &projectPartIdColumn = table.addColumn("projectPartId",
Sqlite::ColumnType::Integer);
table.addColumn("sourceId", Sqlite::ColumnType::Integer);
table.addIndex({projectPartIdColumn});
table.initialize(database);
}
void createProjectPartsSourcesTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("projectPartsSources");
const Sqlite::Column &projectPartIdColumn = table.addColumn("projectPartId",
Sqlite::ColumnType::Integer);
table.addColumn("sourceId", Sqlite::ColumnType::Integer);
table.addIndex({projectPartIdColumn});
table.initialize(database);
}
public:
DatabaseType &database;
};

View File

@@ -33,14 +33,11 @@ class RemoveProjectPartsMessage
{
public:
RemoveProjectPartsMessage() = default;
RemoveProjectPartsMessage(Utils::SmallStringVector &&projectsPartIds)
RemoveProjectPartsMessage(ProjectPartIds &&projectsPartIds)
: projectsPartIds(std::move(projectsPartIds))
{}
Utils::SmallStringVector takeProjectsPartIds()
{
return std::move(projectsPartIds);
}
ProjectPartIds takeProjectsPartIds() { return std::move(projectsPartIds); }
friend QDataStream &operator<<(QDataStream &out, const RemoveProjectPartsMessage &message)
{
@@ -68,11 +65,9 @@ public:
}
public:
Utils::SmallStringVector projectsPartIds;
ProjectPartIds projectsPartIds;
};
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const RemoveProjectPartsMessage &message);
DECLARE_MESSAGE(RemoveProjectPartsMessage)
} // namespace ClangBackEnd

View File

@@ -31,6 +31,7 @@
#include "qtcreatorprojectupdater.h"
#include <filepathcaching.h>
#include <projectpartsstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
@@ -79,11 +80,13 @@ public:
"Creating Dependencies");
Core::ProgressManager::addTask(promise.future(), title, "dependency creation", nullptr);
}};
ClangBackEnd::ProjectPartsStorage<Sqlite::Database> projectPartsStorage{database};
PchManagerClient pchManagerClient{pchCreationProgressManager, dependencyCreationProgressManager};
PchManagerConnectionClient connectionClient{&pchManagerClient};
QtCreatorProjectUpdater<PchManagerProjectUpdater> projectUpdate{connectionClient.serverProxy(),
pchManagerClient,
filePathCache};
filePathCache,
projectPartsStorage};
};
std::unique_ptr<ClangPchManagerPluginData> ClangPchManagerPlugin::d;

View File

@@ -44,10 +44,9 @@ void PchManagerClient::alive()
void PchManagerClient::precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message)
{
for (ClangBackEnd::ProjectPartPch &projectPartPch : message.takeProjectPartPchs()) {
const QString projectPartId{projectPartPch.projectPartId};
const QString pchPath{projectPartPch.pchPath};
addProjectPartPch(std::move(projectPartPch));
precompiledHeaderUpdated(projectPartId, pchPath, projectPartPch.lastModified);
precompiledHeaderUpdated(projectPartPch.projectPartId, pchPath, projectPartPch.lastModified);
}
}
@@ -65,11 +64,10 @@ void PchManagerClient::progress(ClangBackEnd::ProgressMessage &&message)
}
}
void PchManagerClient::precompiledHeaderRemoved(const QString &projectPartId)
void PchManagerClient::precompiledHeaderRemoved(ClangBackEnd::ProjectPartId projectPartId)
{
for (auto notifier : m_notifiers) {
Utils::SmallString id(projectPartId);
removeProjectPartPch(id);
removeProjectPartPch(projectPartId);
notifier->precompiledHeaderRemoved(projectPartId);
}
}
@@ -79,7 +77,8 @@ void PchManagerClient::setConnectionClient(PchManagerConnectionClient *connectio
m_connectionClient = connectionClient;
}
Utils::optional<ClangBackEnd::ProjectPartPch> PchManagerClient::projectPartPch(Utils::SmallStringView projectPartId) const
Utils::optional<ClangBackEnd::ProjectPartPch> PchManagerClient::projectPartPch(
ClangBackEnd::ProjectPartId projectPartId) const
{
auto found = std::lower_bound(m_projectPartPchs.cbegin(),
m_projectPartPchs.cend(),
@@ -110,7 +109,7 @@ void PchManagerClient::detach(PchManagerNotifierInterface *notifierToBeDeleted)
m_notifiers.erase(newEnd, m_notifiers.end());
}
void PchManagerClient::removeProjectPartPch(Utils::SmallStringView projectPartId)
void PchManagerClient::removeProjectPartPch(ClangBackEnd::ProjectPartId projectPartId)
{
auto found = std::lower_bound(m_projectPartPchs.begin(),
m_projectPartPchs.end(),
@@ -145,7 +144,7 @@ const std::vector<PchManagerNotifierInterface *> &PchManagerClient::notifiers()
return m_notifiers;
}
void PchManagerClient::precompiledHeaderUpdated(const QString &projectPartId,
void PchManagerClient::precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId,
const QString &pchFilePath,
long long lastModified)
{

View File

@@ -52,21 +52,20 @@ public:
void precompiledHeadersUpdated(ClangBackEnd::PrecompiledHeadersUpdatedMessage &&message) override;
void progress(ClangBackEnd::ProgressMessage &&message) override;
void precompiledHeaderRemoved(const QString &projectPartId);
void precompiledHeaderRemoved(ClangBackEnd::ProjectPartId projectPartId);
void setConnectionClient(PchManagerConnectionClient *connectionClient);
Utils::optional<ClangBackEnd::ProjectPartPch> projectPartPch(
Utils::SmallStringView projectPartId) const override;
ClangBackEnd::ProjectPartId projectPartId) const override;
const ClangBackEnd::ProjectPartPchs &projectPartPchs() const override
{
return m_projectPartPchs;
}
unittest_public:
const std::vector<PchManagerNotifierInterface*> &notifiers() const;
void precompiledHeaderUpdated(const QString &projectPartId,
unittest_public : const std::vector<PchManagerNotifierInterface *> &notifiers() const;
void precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId,
const QString &pchFilePath,
long long lastModified);
@@ -74,7 +73,7 @@ unittest_public:
void detach(PchManagerNotifierInterface *notifier);
void addProjectPartPch(ClangBackEnd::ProjectPartPch &&projectPartPch);
void removeProjectPartPch(Utils::SmallStringView projectPartId);
void removeProjectPartPch(ClangBackEnd::ProjectPartId projectPartId);
private:
ClangBackEnd::ProjectPartPchs m_projectPartPchs;

View File

@@ -27,6 +27,8 @@
#include "clangpchmanager_global.h"
#include <projectpartid.h>
QT_FORWARD_DECLARE_CLASS(QString)
namespace ClangPchManager {
@@ -40,10 +42,11 @@ public:
PchManagerNotifierInterface(const PchManagerNotifierInterface &) = delete;
PchManagerNotifierInterface &operator=(const PchManagerNotifierInterface &) = delete;
virtual void precompiledHeaderUpdated(const QString &projectPartId,
virtual void precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId,
const QString &pchFilePath,
long long lastModified) = 0;
virtual void precompiledHeaderRemoved(const QString &projectPartId) = 0;
long long lastModified)
= 0;
virtual void precompiledHeaderRemoved(ClangBackEnd::ProjectPartId projectPartId) = 0;
PchManagerClient &m_pchManagerClient;

View File

@@ -29,20 +29,22 @@
namespace ClangPchManager {
PchManagerProjectUpdater::PchManagerProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
PchManagerClient &client,
ClangBackEnd::FilePathCachingInterface &filePathCache)
: ProjectUpdater(server, filePathCache),
m_client(client)
{
}
void PchManagerProjectUpdater::removeProjectParts(const QStringList &projectPartIds)
void PchManagerProjectUpdater::removeProjectParts(const ClangBackEnd::ProjectPartIds &projectPartIds)
{
ProjectUpdater::removeProjectParts(projectPartIds);
for (const QString &projectPartiId : projectPartIds)
m_client.precompiledHeaderRemoved(projectPartiId);
for (ClangBackEnd::ProjectPartId projectPartId : projectPartIds)
m_client.precompiledHeaderRemoved(projectPartId);
}
void PchManagerProjectUpdater::removeProjectParts(const QStringList &projectPartNames)
{
ClangBackEnd::ProjectPartIds projectPartIds = toProjectPartIds(projectPartNames);
ProjectUpdater::removeProjectParts(projectPartIds);
for (ClangBackEnd::ProjectPartId projectPartId : projectPartIds)
m_client.precompiledHeaderRemoved(projectPartId);
}
} // namespace ClangPchManager

View File

@@ -34,9 +34,14 @@ class PchManagerProjectUpdater : public ProjectUpdater
public:
PchManagerProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
PchManagerClient &client,
ClangBackEnd::FilePathCachingInterface &filePathCache);
ClangBackEnd::FilePathCachingInterface &filePathCache,
ClangBackEnd::ProjectPartsStorageInterface &projectPartsStorage)
: ProjectUpdater(server, filePathCache, projectPartsStorage)
, m_client(client)
{}
void removeProjectParts(const QStringList &projectPartIds);
void removeProjectParts(const ClangBackEnd::ProjectPartIds &projectPartIds);
void removeProjectParts(const QStringList &projectPartNames);
private:
PchManagerClient &m_client;

View File

@@ -61,13 +61,6 @@ public:
ClangBackEnd::FilePathIds sources;
};
ProjectUpdater::ProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
ClangBackEnd::FilePathCachingInterface &filePathCache)
: m_server(server),
m_filePathCache(filePathCache)
{
}
void ProjectUpdater::updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts,
Utils::SmallStringVector &&toolChainArguments)
{
@@ -75,9 +68,9 @@ void ProjectUpdater::updateProjectParts(const std::vector<CppTools::ProjectPart
toProjectPartContainers(projectParts), std::move(toolChainArguments)});
}
void ProjectUpdater::removeProjectParts(const QStringList &projectPartIds)
void ProjectUpdater::removeProjectParts(ClangBackEnd::ProjectPartIds projectPartIds)
{
Utils::SmallStringVector sortedIds(projectPartIds);
auto sortedIds{projectPartIds};
std::sort(sortedIds.begin(), sortedIds.end());
m_server.removeProjectParts(ClangBackEnd::RemoveProjectPartsMessage{std::move(sortedIds)});
@@ -278,7 +271,12 @@ ClangBackEnd::ProjectPartContainer ProjectUpdater::toProjectPartContainer(
auto includeSearchPaths = createIncludeSearchPaths(*projectPart);
return ClangBackEnd::ProjectPartContainer(projectPart->id(),
const QByteArray projectPartName = projectPart->id().toUtf8();
ClangBackEnd::ProjectPartId projectPartId = m_projectPartsStorage.fetchProjectPartId(
projectPartName);
return ClangBackEnd::ProjectPartContainer(projectPartId,
Utils::SmallStringVector(arguments),
createCompilerMacros(projectPart->projectMacros),
std::move(includeSearchPaths.system),
@@ -296,9 +294,6 @@ ClangBackEnd::ProjectPartContainers ProjectUpdater::toProjectPartContainers(
{
using namespace std::placeholders;
std::vector<ClangBackEnd::ProjectPartContainer> projectPartContainers;
projectPartContainers.reserve(projectParts.size());
projectParts.erase(std::remove_if(projectParts.begin(),
projectParts.end(),
[](const CppTools::ProjectPart *projectPart) {
@@ -306,6 +301,9 @@ ClangBackEnd::ProjectPartContainers ProjectUpdater::toProjectPartContainers(
}),
projectParts.end());
std::vector<ClangBackEnd::ProjectPartContainer> projectPartContainers;
projectPartContainers.reserve(projectParts.size());
std::transform(projectParts.begin(),
projectParts.end(),
std::back_inserter(projectPartContainers),
@@ -336,4 +334,26 @@ ClangBackEnd::FilePaths ProjectUpdater::createExcludedPaths(
return excludedPaths;
}
QString ProjectUpdater::fetchProjectPartName(ClangBackEnd::ProjectPartId projectPartId) const
{
return m_projectPartsStorage.fetchProjectPartName(projectPartId).toQString();
}
ClangBackEnd::ProjectPartIds ProjectUpdater::toProjectPartIds(
const QStringList &projectPartNames) 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});
});
return projectPartIds;
}
} // namespace ClangPchManager

View File

@@ -33,6 +33,7 @@
#include <generatedfiles.h>
#include <includesearchpath.h>
#include <projectpartcontainer.h>
#include <projectpartsstorageinterface.h>
#include <projectexplorer/headerpath.h>
@@ -69,11 +70,16 @@ public:
};
ProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
ClangBackEnd::FilePathCachingInterface &filePathCache);
ClangBackEnd::FilePathCachingInterface &filePathCache,
ClangBackEnd::ProjectPartsStorageInterface &projectPartsStorage)
: m_server(server)
, m_filePathCache(filePathCache)
, m_projectPartsStorage(projectPartsStorage)
{}
void updateProjectParts(const std::vector<CppTools::ProjectPart *> &projectParts,
Utils::SmallStringVector &&toolChainArguments);
void removeProjectParts(const QStringList &projectPartIds);
void removeProjectParts(ClangBackEnd::ProjectPartIds projectPartIds);
void updateGeneratedFiles(ClangBackEnd::V2::FileContainers &&generatedFiles);
void removeGeneratedFiles(ClangBackEnd::FilePaths &&filePaths);
@@ -88,6 +94,7 @@ public:
CppTools::ProjectPart *projectPart) const;
ClangBackEnd::ProjectPartContainers toProjectPartContainers(
std::vector<CppTools::ProjectPart *> projectParts) const;
void addToHeaderAndSources(HeaderAndSources &headerAndSources,
const CppTools::ProjectFile &projectFile) const;
static QStringList toolChainArguments(CppTools::ProjectPart *projectPart);
@@ -98,11 +105,16 @@ public:
static ClangBackEnd::FilePaths createExcludedPaths(
const ClangBackEnd::V2::FileContainers &generatedFiles);
QString fetchProjectPartName(ClangBackEnd::ProjectPartId projectPartId) const;
ClangBackEnd::ProjectPartIds toProjectPartIds(const QStringList &projectPartNames) const;
private:
ClangBackEnd::GeneratedFiles m_generatedFiles;
ClangBackEnd::FilePaths m_excludedPaths;
ClangBackEnd::ProjectManagementServerInterface &m_server;
ClangBackEnd::FilePathCachingInterface &m_filePathCache;
ClangBackEnd::ProjectPartsStorageInterface &m_projectPartsStorage;
};
} // namespace ClangPchManager

View File

@@ -55,11 +55,12 @@ class QtCreatorProjectUpdater : public ProjectUpdaterType,
public ProjectExplorer::ExtraCompilerFactoryObserver
{
public:
template <typename ClientType>
template<typename ClientType>
QtCreatorProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
ClientType &client,
ClangBackEnd::FilePathCachingInterface &filePathCache)
: ProjectUpdaterType(server, client, filePathCache)
ClangBackEnd::FilePathCachingInterface &filePathCache,
ClangBackEnd::ProjectPartsStorageInterface &projectPartsStorage)
: ProjectUpdaterType(server, client, filePathCache, projectPartsStorage)
{
connectToCppModelManager();
}

View File

@@ -36,6 +36,7 @@
#include <clangpchmanager/clangpchmanagerplugin.h>
#include <clangpchmanager/progressmanager.h>
#include <clangsupport/refactoringdatabaseinitializer.h>
#include <projectpartsstorage.h>
#include <cpptools/cppmodelmanager.h>
@@ -61,6 +62,8 @@ namespace ClangRefactoring {
namespace {
using ClangPchManager::ClangPchManagerPlugin;
QString backendProcessPath()
{
return Core::ICore::libexecPath()
@@ -91,14 +94,16 @@ public:
ClangBackEnd::RefactoringConnectionClient connectionClient{&refactoringClient};
QuerySqliteReadStatementFactory statementFactory{database};
SymbolQuery<QuerySqliteReadStatementFactory> symbolQuery{statementFactory};
ClangBackEnd::ProjectPartsStorage<Sqlite::Database> projectPartsStorage{database};
RefactoringEngine engine{connectionClient.serverProxy(), refactoringClient, filePathCache, symbolQuery};
QtCreatorSearch qtCreatorSearch;
QtCreatorClangQueryFindFilter qtCreatorfindFilter{connectionClient.serverProxy(),
qtCreatorSearch,
refactoringClient};
QtCreatorRefactoringProjectUpdater projectUpdate{connectionClient.serverProxy(),
ClangPchManager::ClangPchManagerPlugin::pchManagerClient(),
filePathCache};
ClangPchManagerPlugin::pchManagerClient(),
filePathCache,
projectPartsStorage};
};
ClangRefactoringPlugin::ClangRefactoringPlugin()

View File

@@ -60,10 +60,16 @@ std::vector<ClangBackEnd::V2::FileContainer> createGeneratedFiles()
}
}
QtCreatorRefactoringProjectUpdater::QtCreatorRefactoringProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
QtCreatorRefactoringProjectUpdater::QtCreatorRefactoringProjectUpdater(
ClangBackEnd::ProjectManagementServerInterface &server,
ClangPchManager::PchManagerClient &pchManagerClient,
ClangBackEnd::FilePathCachingInterface &filePathCache)
: RefactoringProjectUpdater(server, pchManagerClient, *cppModelManager(), filePathCache)
ClangBackEnd::FilePathCachingInterface &filePathCache,
ClangBackEnd::ProjectPartsStorageInterface &projectPartsStorage)
: RefactoringProjectUpdater(server,
pchManagerClient,
*cppModelManager(),
filePathCache,
projectPartsStorage)
{
connectToCppModelManager();
}

View File

@@ -32,9 +32,11 @@ namespace ClangRefactoring {
class QtCreatorRefactoringProjectUpdater final : public RefactoringProjectUpdater
{
public:
QtCreatorRefactoringProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
QtCreatorRefactoringProjectUpdater(
ClangBackEnd::ProjectManagementServerInterface &server,
ClangPchManager::PchManagerClient &pchManagerClient,
ClangBackEnd::FilePathCachingInterface &filePathCache);
ClangBackEnd::FilePathCachingInterface &filePathCache,
ClangBackEnd::ProjectPartsStorageInterface &projectPartsStorage);
private:
void abstractEditorUpdated(const QString &filePath, const QByteArray &contents);

View File

@@ -26,19 +26,22 @@
#include "refactoringprojectupdater.h"
#include <cpptools/cppmodelmanager.h>
#include <projectpartsstorageinterface.h>
namespace ClangRefactoring {
void RefactoringProjectUpdater::precompiledHeaderUpdated(const QString &projectPartId,
void RefactoringProjectUpdater::precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId,
const QString &,
long long)
{
auto projectPart = m_cppModelManager.projectPartForId(projectPartId);
const QString projectPartName = fetchProjectPartName(projectPartId);
auto projectPart = m_cppModelManager.projectPartForId(projectPartName);
if (projectPart)
updateProjectParts({projectPart.data()}, {});
}
void RefactoringProjectUpdater::precompiledHeaderRemoved(const QString &projectPartId)
void RefactoringProjectUpdater::precompiledHeaderRemoved(ClangBackEnd::ProjectPartId projectPartId)
{
removeProjectParts({projectPartId});
}

View File

@@ -39,18 +39,18 @@ public:
RefactoringProjectUpdater(ClangBackEnd::ProjectManagementServerInterface &server,
ClangPchManager::PchManagerClient &pchManagerClient,
CppTools::CppModelManagerInterface &cppModelManager,
ClangBackEnd::FilePathCachingInterface &filePathCache)
: ClangPchManager::ProjectUpdater(server, filePathCache),
ClangPchManager::PchManagerNotifierInterface(pchManagerClient),
m_cppModelManager(cppModelManager)
ClangBackEnd::FilePathCachingInterface &filePathCache,
ClangBackEnd::ProjectPartsStorageInterface &projectPartsStorage)
: ClangPchManager::ProjectUpdater(server, filePathCache, projectPartsStorage)
, ClangPchManager::PchManagerNotifierInterface(pchManagerClient)
, m_cppModelManager(cppModelManager)
{
}
void precompiledHeaderUpdated(const QString &projectPartId,
void precompiledHeaderUpdated(ClangBackEnd::ProjectPartId projectPartId,
const QString &pchFilePath,
long long lastModified) override;
void precompiledHeaderRemoved(const QString &projectPartId) override;
void precompiledHeaderRemoved(ClangBackEnd::ProjectPartId projectPartId) override;
private:
CppTools::CppModelManagerInterface &m_cppModelManager;

View File

@@ -30,11 +30,12 @@
#include <connectionserver.h>
#include <environment.h>
#include <executeinloop.h>
#include <filepathcaching.h>
#include <generatedfiles.h>
#include <modifiedtimechecker.h>
#include <pchcreator.h>
#include <pchmanagerserver.h>
#include <pchmanagerclientproxy.h>
#include <pchmanagerserver.h>
#include <pchtaskgenerator.h>
#include <pchtaskqueue.h>
#include <pchtasksmerger.h>
@@ -42,7 +43,7 @@
#include <processormanager.h>
#include <progresscounter.h>
#include <projectpartsmanager.h>
#include <filepathcaching.h>
#include <projectpartsstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <taskscheduler.h>
@@ -63,14 +64,15 @@ using namespace std::chrono_literals;
using ClangBackEnd::ClangPathWatcher;
using ClangBackEnd::ConnectionServer;
using ClangBackEnd::FilePathCache;
using ClangBackEnd::FilePathView;
using ClangBackEnd::GeneratedFiles;
using ClangBackEnd::PchCreator;
using ClangBackEnd::PchManagerClientProxy;
using ClangBackEnd::PchManagerServer;
using ClangBackEnd::PrecompiledHeaderStorage;
using ClangBackEnd::ProjectPartsManager;
using ClangBackEnd::FilePathCache;
using ClangBackEnd::FilePathView;
using ClangBackEnd::ProjectPartsStorage;
using ClangBackEnd::TimeStamp;
class PchManagerApplication final : public QCoreApplication
@@ -179,7 +181,8 @@ struct Data // because we have a cycle dependency
ClangBackEnd::FilePathCaching filePathCache{database};
ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher{filePathCache};
ApplicationEnvironment environment;
ProjectPartsManager projectParts;
ProjectPartsStorage<> projectPartsStorage{database};
ProjectPartsManager projectParts{projectPartsStorage};
GeneratedFiles generatedFiles;
PchCreatorManager pchCreatorManager{generatedFiles,
environment,

View File

@@ -101,19 +101,15 @@ UsedMacros BuildDependenciesProvider::createUsedMacrosFromStorage(const SourceEn
return usedMacros;
}
std::pair<SourceEntries, int>
BuildDependenciesProvider::createSourceEntriesFromStorage(
const FilePathIds &sourcePathIds,
Utils::SmallStringView projectPartName) const {
std::pair<SourceEntries, ProjectPartId> BuildDependenciesProvider::createSourceEntriesFromStorage(
const FilePathIds &sourcePathIds, ProjectPartId projectPartId) const
{
SourceEntries includes;
Sqlite::DeferredTransaction transaction(m_transactionBackend);
int projectPartId = m_storage.fetchProjectPartId(projectPartName);
for (FilePathId sourcePathId : sourcePathIds) {
SourceEntries entries =
m_storage.fetchDependSources(sourcePathId, projectPartId);
SourceEntries entries = m_storage.fetchDependSources(sourcePathId, projectPartId);
SourceEntries mergedEntries = setUnion<SourceEntries>(includes, entries);
includes = std::move(mergedEntries);
@@ -124,8 +120,9 @@ BuildDependenciesProvider::createSourceEntriesFromStorage(
return {includes, projectPartId};
}
void BuildDependenciesProvider::storeBuildDependency(
const BuildDependency &buildDependency, int projectPartId) {
void BuildDependenciesProvider::storeBuildDependency(const BuildDependency &buildDependency,
ProjectPartId projectPartId)
{
Sqlite::ImmediateTransaction transaction(m_transactionBackend);
m_storage.insertOrUpdateSources(buildDependency.sources, projectPartId);
m_storage.insertOrUpdateFileStatuses(buildDependency.fileStatuses);

View File

@@ -55,9 +55,9 @@ public:
private:
BuildDependency createBuildDependencyFromStorage(SourceEntries &&includes) const;
UsedMacros createUsedMacrosFromStorage(const SourceEntries &includes) const;
std::pair<SourceEntries, int> createSourceEntriesFromStorage(
const FilePathIds &sourcePathIds, Utils::SmallStringView projectPartName) const;
void storeBuildDependency(const BuildDependency &buildDependency, int projectPartId);
std::pair<SourceEntries, ProjectPartId> createSourceEntriesFromStorage(
const FilePathIds &sourcePathIds, ProjectPartId projectPartId) const;
void storeBuildDependency(const BuildDependency &buildDependency, ProjectPartId projectPartId);
private:
BuildDependenciesStorageInterface &m_storage;

View File

@@ -53,17 +53,16 @@ public:
transaction.commit();
}
void insertOrUpdateSources(const SourceEntries &sourceEntries, int projectPartId) override
void insertOrUpdateSources(const SourceEntries &sourceEntries, ProjectPartId projectPartId) override
{
deleteAllProjectPartsSourcesWithProjectPartNameStatement.write(
projectPartId);
deleteAllProjectPartsFilesWithProjectPartNameStatement.write(projectPartId.projectPathId);
for (const SourceEntry &entry : sourceEntries) {
insertOrUpdateProjectPartsSourcesStatement.write(
entry.sourceId.filePathId,
projectPartId,
insertOrUpdateProjectPartsFilesStatement.write(entry.sourceId.filePathId,
projectPartId.projectPathId,
static_cast<uchar>(entry.sourceType),
static_cast<uchar>(entry.hasMissingIncludes));
static_cast<uchar>(
entry.hasMissingIncludes));
}
}
@@ -108,22 +107,22 @@ public:
deleteNewSourceDependenciesStatement.execute();
}
int fetchProjectPartId(Utils::SmallStringView projectPartName) override
ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) override
{
auto projectPartId = fetchProjectPartIdStatement.template value<int>(projectPartName);
auto projectPartId = fetchProjectPartIdStatement.template value<ProjectPartId>(projectPartName);
if (projectPartId)
return projectPartId.value();
return *projectPartId;
insertProjectPartNameStatement.write(projectPartName);
return static_cast<int>(database.lastInsertedRowId());
}
SourceEntries fetchDependSources(FilePathId sourceId, int projectPartId) const override
SourceEntries fetchDependSources(FilePathId sourceId, ProjectPartId projectPartId) const override
{
return fetchSourceDependenciesStatement.template values<SourceEntry, 4>(
300, sourceId.filePathId, projectPartId);
return fetchSourceDependenciesStatement
.template values<SourceEntry, 4>(300, sourceId.filePathId, projectPartId.projectPathId);
}
UsedMacros fetchUsedMacros(FilePathId sourceId) const override
@@ -131,13 +130,11 @@ public:
return fetchUsedMacrosStatement.template values<UsedMacro, 2>(128, sourceId.filePathId);
}
void updatePchCreationTimeStamp(
long long pchCreationTimeStamp,
Utils::SmallStringView projectPartName) override {
void updatePchCreationTimeStamp(long long pchCreationTimeStamp, ProjectPartId projectPartId) override
{
Sqlite::ImmediateTransaction transaction{database};
updatePchCreationTimeStampStatement.write(pchCreationTimeStamp,
projectPartName);
updatePchCreationTimeStampStatement.write(pchCreationTimeStamp, projectPartId.projectPathId);
transaction.commit();
}
@@ -243,8 +240,8 @@ public:
"DELETE FROM newSourceDependencies",
database
};
WriteStatement insertOrUpdateProjectPartsSourcesStatement{
"INSERT INTO projectPartsSources(sourceId, projectPartId, "
WriteStatement insertOrUpdateProjectPartsFilesStatement{
"INSERT INTO projectPartsFiles(sourceId, projectPartId, "
"sourceType, hasMissingIncludes) VALUES (?001, ?002, ?003, ?004) ON "
"CONFLICT(sourceId, projectPartId) DO UPDATE SET sourceType = ?003, "
"hasMissingIncludes = ?004",
@@ -255,7 +252,7 @@ public:
"collectedDependencies WHERE sourceDependencies.sourceId == "
"collectedDependencies.sourceId) SELECT sourceId, "
"pchCreationTimeStamp, sourceType, hasMissingIncludes FROM "
"collectedDependencies NATURAL JOIN projectPartsSources WHERE "
"collectedDependencies NATURAL JOIN projectPartsFiles WHERE "
"projectPartId = ? ORDER BY sourceId",
database};
mutable ReadStatement fetchProjectPartIdStatement{
@@ -269,11 +266,9 @@ public:
database
};
WriteStatement updatePchCreationTimeStampStatement{
"UPDATE projectPartsSources SET pchCreationTimeStamp = ?001 WHERE "
"projectPartId = (SELECT "
"projectPartId FROM projectParts WHERE projectPartName = ?002)",
"UPDATE projectPartsFiles SET pchCreationTimeStamp = ?001 WHERE projectPartId = ?002",
database};
WriteStatement deleteAllProjectPartsSourcesWithProjectPartNameStatement{
"DELETE FROM projectPartsSources WHERE projectPartId = ?", database};
WriteStatement deleteAllProjectPartsFilesWithProjectPartNameStatement{
"DELETE FROM projectPartsFiles WHERE projectPartId = ?", database};
};
}

View File

@@ -30,6 +30,7 @@
#include <builddependency.h>
#include <filepathid.h>
#include <filestatus.h>
#include <projectpartid.h>
#include <sourcedependency.h>
#include <usedmacro.h>
@@ -44,20 +45,17 @@ public:
BuildDependenciesStorageInterface(const BuildDependenciesStorageInterface &) = delete;
BuildDependenciesStorageInterface &operator=(const BuildDependenciesStorageInterface &) = delete;
virtual void insertOrUpdateSources(const SourceEntries &sourceIds,
int projectPartId) = 0;
virtual void insertOrUpdateSources(const SourceEntries &sourceIds, ProjectPartId projectPartId) = 0;
virtual void insertOrUpdateUsedMacros(const UsedMacros &usedMacros) = 0;
virtual void
insertOrUpdateFileStatuses(const FileStatuses &fileStatuses) = 0;
virtual void insertOrUpdateSourceDependencies(const SourceDependencies &sourceDependencies) = 0;
virtual long long fetchLowestLastModifiedTime(FilePathId sourceId) const = 0;
virtual SourceEntries fetchDependSources(FilePathId sourceId,
int projectPartId) const = 0;
ProjectPartId projectPartId) const = 0;
virtual UsedMacros fetchUsedMacros(FilePathId sourceId) const = 0;
virtual int fetchProjectPartId(Utils::SmallStringView projectPartName) = 0;
virtual void updatePchCreationTimeStamp(long long pchCreationTimeStamp,
Utils::SmallStringView projectPartName)
= 0;
virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) = 0;
virtual void updatePchCreationTimeStamp(long long pchCreationTimeStamp, ProjectPartId projectPartId) = 0;
protected:
~BuildDependenciesStorageInterface() = default;

View File

@@ -83,9 +83,9 @@ void PchManagerServer::removeProjectParts(RemoveProjectPartsMessage &&message)
}
namespace {
Utils::SmallStringVector projectPartIds(const ProjectPartContainers &projectParts)
ProjectPartIds projectPartIds(const ProjectPartContainers &projectParts)
{
Utils::SmallStringVector ids;
ProjectPartIds ids;
ids.reserve(projectParts.size());
std::transform(projectParts.cbegin(),
@@ -118,7 +118,7 @@ void PchManagerServer::removeGeneratedFiles(RemoveGeneratedFilesMessage &&messag
m_generatedFiles.remove(message.takeGeneratedFiles());
}
void PchManagerServer::pathsWithIdsChanged(const Utils::SmallStringVector &ids)
void PchManagerServer::pathsWithIdsChanged(const ProjectPartIds &ids)
{
ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(ids);

View File

@@ -57,7 +57,7 @@ public:
void updateGeneratedFiles(UpdateGeneratedFilesMessage &&message) override;
void removeGeneratedFiles(RemoveGeneratedFilesMessage &&message) override;
void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override;
void pathsWithIdsChanged(const ProjectPartIds &ids) override;
void pathsChanged(const FilePathIds &filePathIds) override;
void setPchCreationProgress(int progress, int total);

View File

@@ -30,6 +30,7 @@
#include <compilermacro.h>
#include <filepath.h>
#include <includesearchpath.h>
#include <projectpartid.h>
#include <utils/smallstringvector.h>
#include <utils/cpplanguage_details.h>
@@ -39,11 +40,11 @@ namespace ClangBackEnd {
class PchTask
{
public:
PchTask(Utils::SmallString &&projectPartId,
PchTask(ProjectPartId projectPartId,
FilePathIds &&includes,
FilePathIds &&sources,
CompilerMacros &&compilerMacros,
Utils::SmallStringVector &&usedMacros,
Utils::SmallStringVector &&usedMacros, // TODO remove
Utils::SmallStringVector toolChainArguments,
IncludeSearchPaths systemIncludeSearchPaths,
IncludeSearchPaths projectIncludeSearchPaths,
@@ -62,11 +63,11 @@ public:
, languageExtension(languageExtension)
{}
PchTask(Utils::SmallStringVector &&projectPartIds,
PchTask(ProjectPartIds &&projectPartIds,
FilePathIds &&includes,
FilePathIds &&sources,
CompilerMacros &&compilerMacros,
Utils::SmallStringVector &&usedMacros,
Utils::SmallStringVector &&usedMacros, // TODO remove
Utils::SmallStringVector toolChainArguments,
IncludeSearchPaths systemIncludeSearchPaths,
IncludeSearchPaths projectIncludeSearchPaths,
@@ -98,11 +99,11 @@ public:
&& first.languageExtension == second.languageExtension;
}
Utils::SmallStringView projectPartId() const { return projectPartIds.front(); }
ProjectPartId projectPartId() const { return projectPartIds.front(); }
public:
FilePath systemPchPath;
Utils::SmallStringVector projectPartIds;
ProjectPartIds projectPartIds;
FilePathIds includes;
FilePathIds sources;
CompilerMacros compilerMacros;

View File

@@ -49,7 +49,7 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
buildDependency.usedMacros,
projectPart.compilerMacros};
pchTaskSets.emplace_back(PchTask{projectPart.projectPartId.clone(),
pchTaskSets.emplace_back(PchTask{projectPart.projectPartId,
std::move(filter.topSystemIncludes),
{},
std::move(filter.systemCompilerMacros),
@@ -60,7 +60,7 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
projectPart.language,
projectPart.languageVersion,
projectPart.languageExtension},
PchTask{std::move(projectPart.projectPartId),
PchTask{projectPart.projectPartId,
std::move(filter.topProjectIncludes),
std::move(filter.sources),
std::move(filter.projectCompilerMacros),
@@ -77,7 +77,7 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
m_pchTasksMergerInterface.mergeTasks(std::move(pchTaskSets), std::move(toolChainArguments));
}
void PchTaskGenerator::removeProjectParts(const Utils::SmallStringVector &projectsPartIds)
void PchTaskGenerator::removeProjectParts(const ProjectPartIds &projectsPartIds)
{
m_pchTasksMergerInterface.removePchTasks(projectsPartIds);
}

View File

@@ -50,8 +50,8 @@ public:
{}
void addProjectParts(ProjectPartContainers &&projectParts,
Utils::SmallStringVector &&toolChainArguments);
void removeProjectParts(const Utils::SmallStringVector &projectsPartIds);
Utils::SmallStringVector &&toolChainArguments) override;
void removeProjectParts(const ProjectPartIds &projectsPartIds) override;
private:
BuildDependenciesProviderInterface &m_buildDependenciesProvider;

View File

@@ -35,7 +35,7 @@ public:
virtual void addProjectParts(ProjectPartContainers &&projectParts,
Utils::SmallStringVector &&toolChainArguments)
= 0;
virtual void removeProjectParts(const Utils::SmallStringVector &projectsPartIds) = 0;
virtual void removeProjectParts(const ProjectPartIds &projectsPartIds) = 0;
protected:
~PchTaskGeneratorInterface() = default;

View File

@@ -54,18 +54,18 @@ void PchTaskQueue::addPchTasks(PchTasks &&newPchTasks, PchTasks &destination)
m_progressCounter.addTotal(int(destination.size() - oldSize));
}
void PchTaskQueue::removePchTasksByProjectPartId(const Utils::SmallStringVector &projectsPartIds,
void PchTaskQueue::removePchTasksByProjectPartId(const ProjectPartIds &projectsPartIds,
PchTasks &destination)
{
class CompareDifference
{
public:
bool operator()(const PchTask &first, const Utils::SmallString &second)
bool operator()(const PchTask &first, ProjectPartId second)
{
return first.projectPartId() < second;
}
bool operator()(const Utils::SmallString &first, const PchTask &second)
bool operator()(ProjectPartId first, const PchTask &second)
{
return first < second.projectPartId();
}
@@ -97,7 +97,7 @@ void PchTaskQueue::addProjectPchTasks(PchTasks &&pchTasks)
addPchTasks(std::move(pchTasks), m_projectPchTasks);
}
void PchTaskQueue::removePchTasks(const Utils::SmallStringVector &projectsPartIds)
void PchTaskQueue::removePchTasks(const ProjectPartIds &projectsPartIds)
{
removePchTasksByProjectPartId(projectsPartIds, m_projectPchTasks);
}

View File

@@ -56,7 +56,7 @@ public:
void addSystemPchTasks(PchTasks &&pchTasks) override;
void addProjectPchTasks(PchTasks &&pchTasks) override;
void removePchTasks(const Utils::SmallStringVector &projectsPartIds) override;
void removePchTasks(const ProjectPartIds &projectsPartIds) override;
void processEntries() override;
@@ -68,8 +68,7 @@ public:
private:
void addPchTasks(PchTasks &&pchTasks, PchTasks &destination);
void removePchTasksByProjectPartId(const Utils::SmallStringVector &projectsPartIds,
PchTasks &destination);
void removePchTasksByProjectPartId(const ProjectPartIds &projectsPartIds, PchTasks &destination);
void processProjectPchTasks();
void processSystemPchTasks();

View File

@@ -35,7 +35,7 @@ class PchTaskQueueInterface : public QueueInterface
public:
virtual void addSystemPchTasks(PchTasks &&pchTasks) = 0;
virtual void addProjectPchTasks(PchTasks &&pchTasks) = 0;
virtual void removePchTasks(const Utils::SmallStringVector &projectsPartIds) = 0;
virtual void removePchTasks(const ProjectPartIds &projectsPartIds) = 0;
protected:
~PchTaskQueueInterface() = default;

View File

@@ -37,7 +37,7 @@ void PchTasksMerger::mergeTasks(PchTaskSets &&taskSets,
m_pchTaskQueue.processEntries();
}
void PchTasksMerger::removePchTasks(const Utils::SmallStringVector &projectPartIds)
void PchTasksMerger::removePchTasks(const ProjectPartIds &projectPartIds)
{
m_pchTaskQueue.removePchTasks(projectPartIds);
}

View File

@@ -40,7 +40,7 @@ public:
{}
void mergeTasks(PchTaskSets &&taskSets, Utils::SmallStringVector &&toolChainArguments) override;
void removePchTasks(const Utils::SmallStringVector &projectPartIds) override;
void removePchTasks(const ProjectPartIds &projectPartIds) override;
static CompilerMacros mergeMacros(const CompilerMacros &firstCompilerMacros,
const CompilerMacros &secondCompilerMacros);

View File

@@ -32,7 +32,7 @@ class PchTasksMergerInterface
{
public:
virtual void mergeTasks(PchTaskSets &&taskSets, Utils::SmallStringVector &&toolChainArguments) = 0;
virtual void removePchTasks(const Utils::SmallStringVector &projectPartIds) = 0;
virtual void removePchTasks(const ProjectPartIds &projectPartIds) = 0;
protected:
~PchTasksMergerInterface() = default;

View File

@@ -41,129 +41,125 @@ class PrecompiledHeaderStorage final : public PrecompiledHeaderStorageInterface
using WriteStatement = typename Database::WriteStatement;
public:
PrecompiledHeaderStorage(Database &database)
: m_transaction(database),
m_database(database)
: transaction(database)
, database(database)
{
m_transaction.commit();
transaction.commit();
}
void insertProjectPrecompiledHeader(Utils::SmallStringView projectPartName,
void insertProjectPrecompiledHeader(ProjectPartId projectPartId,
Utils::SmallStringView pchPath,
long long pchBuildTime) override
{
try {
Sqlite::ImmediateTransaction transaction{m_database};
Sqlite::ImmediateTransaction transaction{database};
m_insertProjectPartStatement.write(projectPartName);
m_insertProjectPrecompiledHeaderStatement.write(projectPartName, pchPath, pchBuildTime);
insertProjectPrecompiledHeaderStatement.write(projectPartId.projectPathId,
pchPath,
pchBuildTime);
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
insertProjectPrecompiledHeader(projectPartName, pchPath, pchBuildTime);
} catch (const Sqlite::StatementIsBusy &) {
insertProjectPrecompiledHeader(projectPartId, pchPath, pchBuildTime);
}
}
void deleteProjectPrecompiledHeader(Utils::SmallStringView projectPartName) override
void deleteProjectPrecompiledHeader(ProjectPartId projectPartId) override
{
try {
Sqlite::ImmediateTransaction transaction{m_database};
Sqlite::ImmediateTransaction transaction{database};
m_deleteProjectPrecompiledHeaderStatement.write(projectPartName);
deleteProjectPrecompiledHeaderStatement.write(projectPartId.projectPathId);
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
deleteProjectPrecompiledHeader(projectPartName);
deleteProjectPrecompiledHeader(projectPartId);
}
}
void insertSystemPrecompiledHeaders(const Utils::SmallStringVector &projectPartNames,
void insertSystemPrecompiledHeaders(const ProjectPartIds &projectPartIds,
Utils::SmallStringView pchPath,
long long pchBuildTime) override
{
try {
Sqlite::ImmediateTransaction transaction{m_database};
Sqlite::ImmediateTransaction transaction{database};
for (Utils::SmallStringView projectPartName : projectPartNames) {
m_insertProjectPartStatement.write(projectPartName);
m_insertSystemPrecompiledHeaderStatement.write(projectPartName, pchPath, pchBuildTime);
for (ProjectPartId projectPartId : projectPartIds) {
insertSystemPrecompiledHeaderStatement.write(projectPartId.projectPathId,
pchPath,
pchBuildTime);
}
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
insertSystemPrecompiledHeaders(projectPartNames, pchPath, pchBuildTime);
insertSystemPrecompiledHeaders(projectPartIds, pchPath, pchBuildTime);
}
}
void deleteSystemPrecompiledHeaders(const Utils::SmallStringVector &projectPartNames) override
void deleteSystemPrecompiledHeaders(const ProjectPartIds &projectPartIds) override
{
try {
Sqlite::ImmediateTransaction transaction{m_database};
Sqlite::ImmediateTransaction transaction{database};
for (Utils::SmallStringView projectPartName : projectPartNames)
m_deleteSystemPrecompiledHeaderStatement.write(projectPartName);
for (ProjectPartId projectPartId : projectPartIds)
deleteSystemPrecompiledHeaderStatement.write(projectPartId.projectPathId);
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
deleteSystemPrecompiledHeaders(projectPartNames);
deleteSystemPrecompiledHeaders(projectPartIds);
}
}
FilePath fetchSystemPrecompiledHeaderPath(Utils::SmallStringView projectPartName) override
FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) override
{
try {
Sqlite::DeferredTransaction transaction{m_database};
Sqlite::DeferredTransaction transaction{database};
auto value = m_fetchSystemPrecompiledHeaderPathStatement.template value<FilePath>(
projectPartName);
auto value = fetchSystemPrecompiledHeaderPathStatement.template value<FilePath>(
projectPartId.projectPathId);
if (value)
return value.value();
return *value;
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
return fetchSystemPrecompiledHeaderPath(projectPartName);
return fetchSystemPrecompiledHeaderPath(projectPartId);
}
return FilePath("");
}
Utils::optional<ProjectPartPch> fetchPrecompiledHeader(int projectPartId) const
Utils::optional<ProjectPartPch> fetchPrecompiledHeader(ProjectPartId projectPartId) const
{
return m_getPrecompiledHeader.template value<ProjectPartPch, 2>(projectPartId);
return getPrecompiledHeader.template value<ProjectPartPch, 3>(projectPartId.projectPathId);
}
public:
Sqlite::ImmediateNonThrowingDestructorTransaction m_transaction;
Database &m_database;
WriteStatement m_insertProjectPrecompiledHeaderStatement{
Sqlite::ImmediateNonThrowingDestructorTransaction transaction;
Database &database;
WriteStatement insertProjectPrecompiledHeaderStatement{
"INSERT INTO precompiledHeaders(projectPartId, projectPchPath, projectPchBuildTime) "
"VALUES((SELECT projectPartId FROM projectParts WHERE projectPartName = ?001),?002,?003) "
"ON CONFLICT (projectPartId) DO UPDATE SET projectPchPath=?002,projectPchBuildTime=?003",
m_database};
WriteStatement m_insertSystemPrecompiledHeaderStatement{
database};
WriteStatement insertSystemPrecompiledHeaderStatement{
"INSERT INTO precompiledHeaders(projectPartId, systemPchPath, systemPchBuildTime) "
"VALUES((SELECT projectPartId FROM projectParts WHERE projectPartName = ?001),?002,?003) "
"VALUES(?001,?002,?003) "
"ON CONFLICT (projectPartId) DO UPDATE SET systemPchPath=?002,systemPchBuildTime=?003",
m_database};
WriteStatement m_insertProjectPartStatement{
"INSERT OR IGNORE INTO projectParts(projectPartName) VALUES (?)", m_database};
WriteStatement m_deleteProjectPrecompiledHeaderStatement{
database};
WriteStatement deleteProjectPrecompiledHeaderStatement{
"UPDATE OR IGNORE precompiledHeaders SET projectPchPath=NULL,projectPchBuildTime=NULL "
"WHERE projectPartId = (SELECT projectPartId FROM "
"projectParts WHERE projectPartName = ?)",
m_database};
WriteStatement m_deleteSystemPrecompiledHeaderStatement{
"WHERE projectPartId = ?",
database};
WriteStatement deleteSystemPrecompiledHeaderStatement{
"UPDATE OR IGNORE precompiledHeaders SET systemPchPath=NULL,systemPchBuildTime=NULL "
"WHERE projectPartId = (SELECT projectPartId FROM "
"projectParts WHERE projectPartName = ?)",
m_database};
ReadStatement m_fetchSystemPrecompiledHeaderPathStatement{
"SELECT systemPchPath FROM precompiledHeaders WHERE projectPartId = (SELECT projectPartId "
"FROM projectParts WHERE projectPartName = ?)",
m_database};
mutable ReadStatement m_getPrecompiledHeader{
"SELECT ifnull(nullif(projectPchPath, ''), systemPchPath), "
"WHERE projectPartId = ?",
database};
ReadStatement fetchSystemPrecompiledHeaderPathStatement{
"SELECT systemPchPath FROM precompiledHeaders WHERE projectPartId = ?", database};
mutable ReadStatement getPrecompiledHeader{
"SELECT projectPartId, ifnull(nullif(projectPchPath, ''), systemPchPath), "
"projectPchBuildTime FROM precompiledHeaders WHERE projectPartId = ?",
m_database};
database};
};
}

View File

@@ -28,6 +28,7 @@
#include "projectpartpch.h"
#include <filepath.h>
#include <projectpartid.h>
#include <utils/smallstringvector.h>
#include <utils/optional.h>
@@ -42,18 +43,18 @@ public:
PrecompiledHeaderStorageInterface(const PrecompiledHeaderStorageInterface &) = delete;
PrecompiledHeaderStorageInterface &operator=(const PrecompiledHeaderStorageInterface &) = delete;
virtual void insertProjectPrecompiledHeader(Utils::SmallStringView projectPartName,
virtual void insertProjectPrecompiledHeader(ProjectPartId projectPartId,
Utils::SmallStringView pchPath,
long long pchBuildTime)
= 0;
virtual void deleteProjectPrecompiledHeader(Utils::SmallStringView projectPartName) = 0;
virtual void insertSystemPrecompiledHeaders(const Utils::SmallStringVector &projectPartNames,
virtual void deleteProjectPrecompiledHeader(ProjectPartId projectPartName) = 0;
virtual void insertSystemPrecompiledHeaders(const ProjectPartIds &projectPartIds,
Utils::SmallStringView pchPath,
long long pchBuildTime)
= 0;
virtual void deleteSystemPrecompiledHeaders(const Utils::SmallStringVector &projectPartNames) = 0;
virtual FilePath fetchSystemPrecompiledHeaderPath(Utils::SmallStringView projectPartName) = 0;
virtual Utils::optional<ProjectPartPch> fetchPrecompiledHeader(int projectPartId) const = 0;
virtual void deleteSystemPrecompiledHeaders(const ProjectPartIds &projectPartIds) = 0;
virtual FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) = 0;
virtual Utils::optional<ProjectPartPch> fetchPrecompiledHeader(ProjectPartId projectPartId) const = 0;
protected:
~PrecompiledHeaderStorageInterface() = default;

View File

@@ -32,44 +32,115 @@
namespace ClangBackEnd {
inline namespace Pch {
ProjectPartIds toProjectPartIds(const ProjectPartContainers &projectsParts)
{
ProjectPartIds ids;
ids.reserve(projectsParts.size());
std::transform(projectsParts.begin(),
projectsParts.end(),
std::back_inserter(ids),
[](const auto &projectPart) { return projectPart.projectPartId; });
return ids;
}
ProjectPartContainers ProjectPartsManager::update(ProjectPartContainers &&projectsParts)
{
auto updatedProjectPartContainers = newProjectParts(std::move(projectsParts));
auto updatedProjectParts = filterNewProjectParts(std::move(projectsParts), m_projectParts);
mergeProjectParts(updatedProjectPartContainers);
if (updatedProjectParts.empty())
return {};
return updatedProjectPartContainers;
auto persistentProjectParts = m_projectPartsStorage.fetchProjectParts(
toProjectPartIds(updatedProjectParts));
if (persistentProjectParts.size() > 0) {
mergeProjectParts(persistentProjectParts);
updatedProjectParts = filterNewProjectParts(std::move(updatedProjectParts),
persistentProjectParts);
if (updatedProjectParts.empty())
return {};
}
m_projectPartsStorage.updateProjectParts(updatedProjectParts);
mergeProjectParts(updatedProjectParts);
return updatedProjectParts;
}
void ProjectPartsManager::remove(const Utils::SmallStringVector &ids)
void ProjectPartsManager::remove(const ProjectPartIds &projectPartIds)
{
auto shouldRemove = [&] (const ProjectPartContainer &projectPart) {
return std::find(ids.begin(), ids.end(), projectPart.projectPartId) != ids.end();
ProjectPartContainers projectPartsWithoutIds;
struct Compare
{
bool operator()(ProjectPartId first, const ProjectPartContainer &second)
{
return first < second.projectPartId;
}
bool operator()(ProjectPartId first, const ProjectPartId &second) { return first < second; }
bool operator()(const ProjectPartContainer &first, const ProjectPartContainer &second)
{
return first.projectPartId < second.projectPartId;
}
bool operator()(const ProjectPartContainer &first, ProjectPartId second)
{
return first.projectPartId < second;
}
};
auto newEnd = std::remove_if(m_projectParts.begin(), m_projectParts.end(), shouldRemove);
m_projectParts.erase(newEnd, m_projectParts.end());
std::set_difference(std::make_move_iterator(m_projectParts.begin()),
std::make_move_iterator(m_projectParts.end()),
projectPartIds.begin(),
projectPartIds.end(),
std::back_inserter(projectPartsWithoutIds),
Compare{});
m_projectParts = std::move(projectPartsWithoutIds);
}
ProjectPartContainers ProjectPartsManager::projects(const Utils::SmallStringVector &projectPartIds) const
ProjectPartContainers ProjectPartsManager::projects(const ProjectPartIds &projectPartIds) const
{
ProjectPartContainers projectPartsWithIds;
std::copy_if(m_projectParts.begin(),
struct Compare
{
bool operator()(ProjectPartId first, const ProjectPartContainer &second)
{
return first < second.projectPartId;
}
bool operator()(ProjectPartId first, const ProjectPartId &second) { return first < second; }
bool operator()(const ProjectPartContainer &first, const ProjectPartContainer &second)
{
return first.projectPartId < second.projectPartId;
}
bool operator()(const ProjectPartContainer &first, ProjectPartId second)
{
return first.projectPartId < second;
}
};
std::set_intersection(m_projectParts.begin(),
m_projectParts.end(),
projectPartIds.begin(),
projectPartIds.end(),
std::back_inserter(projectPartsWithIds),
[&] (const ProjectPartContainer &projectPart) {
return std::binary_search(projectPartIds.begin(), projectPartIds.end(), projectPart.projectPartId);
});
Compare{});
return projectPartsWithIds;
}
void ProjectPartsManager::updateDeferred(const ProjectPartContainers &deferredProjectsParts)
{
using ProjectPartContainerReferences = std::vector<std::reference_wrapper<ProjectPartContainer>>;
ProjectPartContainerReferences deferredProjectPartPointers;
deferredProjectPartPointers.reserve(deferredProjectsParts.size());
@@ -102,15 +173,16 @@ ProjectPartContainers ProjectPartsManager::deferredUpdates()
return deferredProjectParts;
}
ProjectPartContainers ProjectPartsManager::newProjectParts(ProjectPartContainers &&projectsParts) const
ProjectPartContainers ProjectPartsManager::filterNewProjectParts(
ProjectPartContainers &&projectsParts, const ProjectPartContainers &oldProjectParts)
{
ProjectPartContainers updatedProjectPartContainers;
updatedProjectPartContainers.reserve(projectsParts.size());
std::set_difference(std::make_move_iterator(projectsParts.begin()),
std::make_move_iterator(projectsParts.end()),
m_projectParts.begin(),
m_projectParts.end(),
oldProjectParts.begin(),
oldProjectParts.end(),
std::back_inserter(updatedProjectPartContainers));
return updatedProjectPartContainers;

View File

@@ -28,6 +28,7 @@
#include "clangpchmanagerbackend_global.h"
#include <projectpartsmanagerinterface.h>
#include <projectpartsstorageinterface.h>
#include <utils/smallstringvector.h>
@@ -37,18 +38,24 @@ inline namespace Pch {
class ProjectPartsManager final : public ProjectPartsManagerInterface
{
public:
ProjectPartsManager(ProjectPartsStorageInterface &projectPartsStorage)
: m_projectPartsStorage(projectPartsStorage)
{}
ProjectPartContainers update(ProjectPartContainers &&projectsParts) override;
void remove(const Utils::SmallStringVector &projectPartIds) override;
ProjectPartContainers projects(const Utils::SmallStringVector &projectPartIds) const override;
void remove(const ProjectPartIds &projectPartIds) override;
ProjectPartContainers projects(const ProjectPartIds &projectPartIds) const override;
void updateDeferred(const ProjectPartContainers &projectsParts) override;
ProjectPartContainers deferredUpdates() override;
ProjectPartContainers newProjectParts(ProjectPartContainers &&projectsParts) const;
static ProjectPartContainers filterNewProjectParts(ProjectPartContainers &&newProjectsParts,
const ProjectPartContainers &oldProjectParts);
void mergeProjectParts(const ProjectPartContainers &projectsParts);
const ProjectPartContainers &projectParts() const;
private:
ProjectPartContainers m_projectParts;
ProjectPartsStorageInterface &m_projectPartsStorage;
};
} // namespace Pch

View File

@@ -37,10 +37,11 @@ public:
ProjectPartsManagerInterface &operator=(const ProjectPartsManagerInterface &) = delete;
virtual ProjectPartContainers update(ProjectPartContainers &&projectsParts) = 0;
virtual void remove(const Utils::SmallStringVector &projectPartIds) = 0;
virtual ProjectPartContainers projects(const Utils::SmallStringVector &projectPartIds) const = 0;
virtual void remove(const ProjectPartIds &projectPartIds) = 0;
virtual ProjectPartContainers projects(const ProjectPartIds &projectPartIds) const = 0;
virtual void updateDeferred(const ProjectPartContainers &projectsParts) = 0;
virtual ProjectPartContainers deferredUpdates() = 0;
protected:
~ProjectPartsManagerInterface() = default;
};

View File

@@ -33,19 +33,19 @@ namespace ClangBackEnd {
struct ArgumentsEntry
{
ArgumentsEntry(Utils::SmallStringVector &&ids, const Utils::SmallStringVector &arguments)
ArgumentsEntry(ProjectPartIds &&ids, const Utils::SmallStringVector &arguments)
: ids(std::move(ids))
, arguments(arguments)
{}
ArgumentsEntry(const Utils::SmallStringVector &ids, const Utils::SmallStringVector &arguments)
ArgumentsEntry(ProjectPartIds &ids, const Utils::SmallStringVector &arguments)
: ids(ids)
, arguments(arguments)
{}
void mergeIds(Utils::SmallStringVector &&newIds)
void mergeIds(ProjectPartIds &&newIds)
{
Utils::SmallStringVector mergedIds;
ProjectPartIds mergedIds;
mergedIds.reserve(ids.size() + newIds.size());
std::set_union(std::make_move_iterator(ids.begin()),
@@ -54,12 +54,12 @@ struct ArgumentsEntry
std::make_move_iterator(newIds.end()),
std::back_inserter(mergedIds));
ids = mergedIds;
ids = std::move(mergedIds);
}
void removeIds(const Utils::SmallStringVector &idsToBeRemoved)
void removeIds(const ProjectPartIds &idsToBeRemoved)
{
Utils::SmallStringVector idsWithout;
ProjectPartIds idsWithout;
idsWithout.reserve(ids.size());
std::set_difference(std::make_move_iterator(ids.begin()),
std::make_move_iterator(ids.end()),
@@ -67,10 +67,10 @@ struct ArgumentsEntry
idsToBeRemoved.end(),
std::back_inserter(idsWithout));
ids = idsWithout;
ids = std::move(idsWithout);
}
Utils::SmallStringVector ids;
ProjectPartIds ids;
Utils::SmallStringVector arguments;
};
@@ -118,11 +118,11 @@ public:
removeEmptyEntries();
}
void remove(const Utils::SmallStringVector &idsToBeRemoved)
void remove(const ProjectPartIds &idsToBeRemoved)
{
ArgumentsEntries entries;
for (ArgumentsEntry &entry : m_argumentEntries) {
Utils::SmallStringVector usedIds;
ProjectPartIds usedIds;
std::set_difference(entry.ids.begin(),
entry.ids.end(),
idsToBeRemoved.begin(),
@@ -135,11 +135,11 @@ public:
removeEmptyEntries();
}
ArgumentsEntries arguments(const Utils::SmallStringVector &ids) const
ArgumentsEntries arguments(const ProjectPartIds &ids) const
{
ArgumentsEntries entries;
for (const ArgumentsEntry &entry : m_argumentEntries) {
Utils::SmallStringVector usedIds;
ProjectPartIds usedIds;
std::set_intersection(entry.ids.begin(),
entry.ids.end(),
ids.begin(),
@@ -159,9 +159,9 @@ public:
}
private:
static Utils::SmallStringVector createIds(const ProjectPartContainers &projectParts)
static ProjectPartIds createIds(const ProjectPartContainers &projectParts)
{
Utils::SmallStringVector ids;
ProjectPartIds ids;
ids.reserve(projectParts.size());
for (const auto &projectPart : projectParts)
ids.emplace_back(projectPart.projectPartId);
@@ -181,7 +181,7 @@ private:
}
private:
std::vector<ArgumentsEntry> m_argumentEntries;
ArgumentsEntries m_argumentEntries;
};
}

View File

@@ -17,8 +17,6 @@ HEADERS += \
$$PWD/usedmacro.h \
$$PWD/sourcedependency.h \
$$PWD/filestatus.h \
$$PWD/projectpartartefactexception.h \
$$PWD/projectpartartefact.h \
$$PWD/filestatuscache.h \
$$PWD/indexdataconsumer.h \
$$PWD/sourcesmanager.h \
@@ -68,5 +66,4 @@ HEADERS += \
SOURCES += \
$$PWD/sourcerangefilter.cpp \
$$PWD/symbolindexer.cpp \
$$PWD/projectpartartefact.cpp \
$$PWD/filestatuscache.cpp

View File

@@ -209,7 +209,7 @@ public:
if (usr) {
m_symbolEntries.emplace(std::piecewise_construct,
std::forward_as_tuple(globalId),
std::forward_as_tuple(std::move(usr.value()),
std::forward_as_tuple(std::move(*usr),
macroName,
SymbolKind::Macro));
}

View File

@@ -149,7 +149,7 @@ bool IndexDataConsumer::handleDeclOccurence(
auto kindAndTags = symbolKindAndTags(declaration);
m_symbolEntries.emplace(std::piecewise_construct,
std::forward_as_tuple(globalId),
std::forward_as_tuple(std::move(usr.value()),
std::forward_as_tuple(std::move(*usr),
symbolName(namedDeclaration),
kindAndTags.first,
kindAndTags.second));

View File

@@ -65,7 +65,8 @@ SymbolIndexer::SymbolIndexer(SymbolIndexerTaskQueueInterface &symbolIndexerTaskQ
ClangPathWatcherInterface &pathWatcher,
FilePathCachingInterface &filePathCache,
FileStatusCache &fileStatusCache,
Sqlite::TransactionInterface &transactionInterface)
Sqlite::TransactionInterface &transactionInterface,
ProjectPartsStorageInterface &projectPartsStorage)
: m_symbolIndexerTaskQueue(symbolIndexerTaskQueue)
, m_symbolStorage(symbolStorage)
, m_buildDependencyStorage(buildDependenciesStorage)
@@ -74,6 +75,7 @@ SymbolIndexer::SymbolIndexer(SymbolIndexerTaskQueueInterface &symbolIndexerTaskQ
, m_filePathCache(filePathCache)
, m_fileStatusCache(fileStatusCache)
, m_transactionInterface(transactionInterface)
, m_projectPartsStorage(projectPartsStorage)
{
pathWatcher.setNotifier(this);
}
@@ -86,26 +88,13 @@ void SymbolIndexer::updateProjectParts(ProjectPartContainers &&projectParts)
void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
{
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
const auto optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(projectPart.projectPartId);
int projectPartId = m_symbolStorage.insertOrUpdateProjectPart(
projectPart.projectPartId,
projectPart.toolChainArguments,
projectPart.compilerMacros,
projectPart.systemIncludeSearchPaths,
projectPart.projectIncludeSearchPaths,
projectPart.language,
projectPart.languageVersion,
projectPart.languageExtension);
if (optionalArtefact)
projectPartId = optionalArtefact->projectPartId;
Sqlite::DeferredTransaction transaction{m_transactionInterface};
ProjectPartId projectPartId = projectPart.projectPartId;
const Utils::optional<ProjectPartPch> optionalProjectPartPch
= m_precompiledHeaderStorage.fetchPrecompiledHeader(projectPartId);
FilePathIds sourcePathIds = updatableFilePathIds(projectPart, optionalArtefact);
transaction.commit();
if (sourcePathIds.empty())
return;
using Builder = CommandLineBuilder<ProjectPartContainer, Utils::SmallStringVector>;
Builder commandLineBuilder{projectPart,
@@ -113,8 +102,7 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
InputFileType::Source,
{},
{},
optionalProjectPartPch
? FilePathView{optionalProjectPartPch.value().pchPath}
optionalProjectPartPch ? FilePathView{optionalProjectPartPch->pchPath}
: FilePathView{}};
std::vector<SymbolIndexerTask> symbolIndexerTask;
@@ -132,14 +120,6 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations());
m_buildDependencyStorage.insertOrUpdateUsedMacros(symbolsCollector.usedMacros());
m_buildDependencyStorage.insertOrUpdateFileStatuses(symbolsCollector.fileStatuses());
m_buildDependencyStorage.insertOrUpdateSourceDependencies(
symbolsCollector.sourceDependencies());
transaction.commit();
}
};
@@ -151,9 +131,7 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
m_symbolIndexerTaskQueue.processEntries();
}
void SymbolIndexer::pathsWithIdsChanged(const Utils::SmallStringVector &)
{
}
void SymbolIndexer::pathsWithIdsChanged(const ProjectPartIds &) {}
void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds)
{
@@ -173,8 +151,8 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
m_fileStatusCache.update(filePathId);
Sqlite::DeferredTransaction transaction{m_transactionInterface};
const Utils::optional<ProjectPartArtefact> optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(
filePathId);
const Utils::optional<ProjectPartArtefact>
optionalArtefact = m_projectPartsStorage.fetchProjectPartArtefact(filePathId);
if (!optionalArtefact)
return;
@@ -182,9 +160,9 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
= m_precompiledHeaderStorage.fetchPrecompiledHeader(optionalArtefact->projectPartId);
transaction.commit();
const ProjectPartArtefact &artefact = optionalArtefact.value();
const ProjectPartArtefact &artefact = *optionalArtefact;
auto pchPath = optionalProjectPartPch ? optionalProjectPartPch.value().pchPath : FilePath{};
auto pchPath = optionalProjectPartPch ? optionalProjectPartPch->pchPath : FilePath{};
CommandLineBuilder<ProjectPartArtefact, Utils::SmallStringVector>
builder{artefact, artefact.toolChainArguments, InputFileType::Source, {}, {}, pchPath};
@@ -201,13 +179,6 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations());
m_buildDependencyStorage.insertOrUpdateUsedMacros(symbolsCollector.usedMacros());
m_buildDependencyStorage.insertOrUpdateFileStatuses(symbolsCollector.fileStatuses());
m_buildDependencyStorage.insertOrUpdateSourceDependencies(
symbolsCollector.sourceDependencies());
transaction.commit();
}
};

View File

@@ -31,9 +31,10 @@
#include "builddependenciesstorageinterface.h"
#include "clangpathwatcher.h"
#include <filecontainerv2.h>
#include <precompiledheaderstorageinterface.h>
#include <projectpartcontainer.h>
#include <filecontainerv2.h>
#include <projectpartsstorageinterface.h>
namespace ClangBackEnd {
@@ -49,12 +50,13 @@ public:
ClangPathWatcherInterface &pathWatcher,
FilePathCachingInterface &filePathCache,
FileStatusCache &fileStatusCache,
Sqlite::TransactionInterface &transactionInterface);
Sqlite::TransactionInterface &transactionInterface,
ProjectPartsStorageInterface &projectPartsStorage);
void updateProjectParts(ProjectPartContainers &&projectParts);
void updateProjectPart(ProjectPartContainer &&projectPart);
void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override;
void pathsWithIdsChanged(const ProjectPartIds &ids) override;
void pathsChanged(const FilePathIds &filePathIds) override;
void updateChangedPath(FilePathId filePath,
std::vector<SymbolIndexerTask> &symbolIndexerTask);
@@ -78,6 +80,7 @@ private:
FilePathCachingInterface &m_filePathCache;
FileStatusCache &m_fileStatusCache;
Sqlite::TransactionInterface &m_transactionInterface;
ProjectPartsStorageInterface &m_projectPartsStorage;
};
} // namespace ClangBackEnd

View File

@@ -26,6 +26,7 @@
#pragma once
#include <filepathid.h>
#include <projectpartid.h>
#include <functional>
@@ -43,12 +44,10 @@ class SymbolIndexerTask
public:
using Callable = std::function<void(SymbolsCollectorInterface &symbolsCollector)>;
SymbolIndexerTask(FilePathId filePathId,
int projectPartId,
Callable &&callable)
: callable(std::move(callable)),
filePathId(filePathId),
projectPartId(projectPartId)
SymbolIndexerTask(FilePathId filePathId, ProjectPartId projectPartId, Callable &&callable)
: callable(std::move(callable))
, filePathId(filePathId)
, projectPartId(projectPartId)
{
}
@@ -78,7 +77,7 @@ public:
public:
Callable callable;
FilePathId filePathId;
int projectPartId;
ProjectPartId projectPartId;
};
} // namespace ClangBackEnd

View File

@@ -36,6 +36,7 @@
#include <builddependenciesstorage.h>
#include <precompiledheaderstorage.h>
#include <projectpartsstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <filepathcachingfwd.h>
@@ -84,7 +85,8 @@ public:
ProgressCounter::SetProgressCallback &&setProgressCallback)
: m_filePathCache(filePathCache)
, m_buildDependencyStorage(database)
, m_recompiledHeaderStorage(database)
, m_precompiledHeaderStorage(database)
, m_projectPartsStorage(database)
, m_symbolStorage(database)
, m_collectorManger(generatedFiles, database)
, m_progressCounter(std::move(setProgressCallback))
@@ -121,7 +123,8 @@ private:
using SymbolIndexerTaskScheduler = TaskScheduler<SymbolsCollectorManager, SymbolIndexerTask::Callable>;
FilePathCachingInterface &m_filePathCache;
BuildDependenciesStorage m_buildDependencyStorage;
PrecompiledHeaderStorage<Sqlite::Database> m_recompiledHeaderStorage;
PrecompiledHeaderStorage<Sqlite::Database> m_precompiledHeaderStorage;
ProjectPartsStorage<Sqlite::Database> m_projectPartsStorage;
SymbolStorage m_symbolStorage;
ClangPathWatcher<QFileSystemWatcher, QTimer> m_sourceWatcher{m_filePathCache};
FileStatusCache m_fileStatusCache{m_filePathCache};
@@ -130,11 +133,12 @@ private:
SymbolIndexer m_indexer{m_indexerQueue,
m_symbolStorage,
m_buildDependencyStorage,
m_recompiledHeaderStorage,
m_precompiledHeaderStorage,
m_sourceWatcher,
m_filePathCache,
m_fileStatusCache,
m_symbolStorage.m_database};
m_symbolStorage.database,
m_projectPartsStorage};
SymbolIndexerTaskQueue m_indexerQueue{m_indexerScheduler, m_progressCounter};
SymbolIndexerTaskScheduler m_indexerScheduler;
};

View File

@@ -50,10 +50,10 @@ class SymbolStorage final : public SymbolStorageInterface
public:
SymbolStorage(Database &database)
: m_transaction(database),
m_database(database)
: transaction(database)
, database(database)
{
m_transaction.commit();
transaction.commit();
}
void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
@@ -70,91 +70,9 @@ public:
deleteNewLocationsTable();
}
int insertOrUpdateProjectPart(Utils::SmallStringView projectPartName,
const Utils::SmallStringVector &toolChainArguments,
const CompilerMacros &compilerMacros,
const IncludeSearchPaths &systemIncludeSearchPaths,
const IncludeSearchPaths &projectIncludeSearchPaths,
Utils::Language language,
Utils::LanguageVersion languageVersion,
Utils::LanguageExtension languageExtension) override
{
Utils::SmallString toolChainArgumentsAsJson = toJson(toolChainArguments);
Utils::SmallString compilerMacrosAsJson = toJson(compilerMacros);
Utils::SmallString systemIncludeSearchPathsAsJason = toJson(systemIncludeSearchPaths);
Utils::SmallString projectIncludeSearchPathsAsJason = toJson(projectIncludeSearchPaths);
m_insertOrUpdateProjectPartStatement.write(projectPartName,
toolChainArgumentsAsJson,
compilerMacrosAsJson,
systemIncludeSearchPathsAsJason,
projectIncludeSearchPathsAsJason,
static_cast<int>(language),
static_cast<int>(languageVersion),
static_cast<int>(languageExtension));
auto projectPartId = m_getProjectPartIdStatement.template value<int>(projectPartName);
return projectPartId.value();
}
Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const override
{
ReadStatement &statement = m_getProjectPartArtefactsBySourceId;
return statement.template value<ProjectPartArtefact, 8>(sourceId.filePathId);
}
Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(Utils::SmallStringView projectPartName) const override
{
ReadStatement &statement = m_getProjectPartArtefactsByProjectPartName;
return statement.template value<ProjectPartArtefact, 8>(projectPartName);
}
static Utils::SmallString toJson(const Utils::SmallStringVector &strings)
{
QJsonDocument document;
QJsonArray array;
std::transform(strings.begin(), strings.end(), std::back_inserter(array), [] (const auto &string) {
return QJsonValue(string.data());
});
document.setArray(array);
return document.toJson(QJsonDocument::Compact);
}
static Utils::SmallString toJson(const CompilerMacros &compilerMacros)
{
QJsonDocument document;
QJsonArray array;
for (const CompilerMacro &macro : compilerMacros)
array.push_back(QJsonArray{{QString(macro.key), QString(macro.value), macro.index}});
document.setArray(array);
return document.toJson(QJsonDocument::Compact);
}
static Utils::SmallString toJson(const IncludeSearchPaths &includeSearchPaths)
{
QJsonDocument document;
QJsonArray array;
for (const IncludeSearchPath &path : includeSearchPaths)
array.push_back(QJsonArray{{path.path.data(), path.index, int(path.type)}});
document.setArray(array);
return document.toJson(QJsonDocument::Compact);
}
void fillTemporarySymbolsTable(const SymbolEntries &symbolEntries)
{
WriteStatement &statement = m_insertSymbolsToNewSymbolsStatement;
WriteStatement &statement = insertSymbolsToNewSymbolsStatement;
for (const auto &symbolEntry : symbolEntries) {
statement.write(symbolEntry.first,
@@ -166,7 +84,7 @@ public:
void fillTemporaryLocationsTable(const SourceLocationEntries &sourceLocations)
{
WriteStatement &statement = m_insertLocationsToNewLocationsStatement;
WriteStatement &statement = insertLocationsToNewLocationsStatement;
for (const auto &locationEntry : sourceLocations) {
statement.write(locationEntry.symbolId,
@@ -177,40 +95,22 @@ public:
}
}
void addNewSymbolsToSymbols()
{
m_addNewSymbolsToSymbolsStatement.execute();
}
void addNewSymbolsToSymbols() { addNewSymbolsToSymbolsStatement.execute(); }
void syncNewSymbolsFromSymbols()
{
m_syncNewSymbolsFromSymbolsStatement.execute();
}
void syncNewSymbolsFromSymbols() { syncNewSymbolsFromSymbolsStatement.execute(); }
void syncSymbolsIntoNewLocations()
{
m_syncSymbolsIntoNewLocationsStatement.execute();
}
void syncSymbolsIntoNewLocations() { syncSymbolsIntoNewLocationsStatement.execute(); }
void deleteAllLocationsFromUpdatedFiles()
{
m_deleteAllLocationsFromUpdatedFilesStatement.execute();
deleteAllLocationsFromUpdatedFilesStatement.execute();
}
void insertNewLocationsInLocations()
{
m_insertNewLocationsInLocationsStatement.execute();
}
void insertNewLocationsInLocations() { insertNewLocationsInLocationsStatement.execute(); }
void deleteNewSymbolsTable()
{
m_deleteNewSymbolsTableStatement.execute();
}
void deleteNewSymbolsTable() { deleteNewSymbolsTableStatement.execute(); }
void deleteNewLocationsTable()
{
m_deleteNewLocationsTableStatement.execute();
}
void deleteNewLocationsTable() { deleteNewLocationsTableStatement.execute(); }
SourceLocationEntries sourceLocations() const
{
@@ -230,7 +130,7 @@ public:
table.addIndex({usrColumn, symbolNameColumn});
table.addIndex({symbolIdColumn});
table.initialize(m_database);
table.initialize(database);
return table;
}
@@ -248,85 +148,49 @@ public:
table.addColumn("locationKind", Sqlite::ColumnType::Integer);
table.addUniqueIndex({sourceIdColumn, lineColumn, columnColumn});
table.initialize(m_database);
table.initialize(database);
return table;
}
public:
Sqlite::ImmediateNonThrowingDestructorTransaction m_transaction;
Database &m_database;
Sqlite::ImmediateNonThrowingDestructorTransaction transaction;
Database &database;
Sqlite::Table newSymbolsTablet{createNewSymbolsTable()};
Sqlite::Table newLocationsTable{createNewLocationsTable()};
WriteStatement m_insertSymbolsToNewSymbolsStatement{
WriteStatement insertSymbolsToNewSymbolsStatement{
"INSERT INTO newSymbols(temporarySymbolId, usr, symbolName, symbolKind) VALUES(?,?,?,?)",
m_database};
WriteStatement m_insertLocationsToNewLocationsStatement{
"INSERT OR IGNORE INTO newLocations(temporarySymbolId, line, column, sourceId, locationKind) VALUES(?,?,?,?,?)",
m_database
};
ReadStatement m_selectNewSourceIdsStatement{
"SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources WHERE newLocations.sourceId == sources.sourceId)",
m_database
};
WriteStatement m_addNewSymbolsToSymbolsStatement{
database};
WriteStatement insertLocationsToNewLocationsStatement{
"INSERT OR IGNORE INTO newLocations(temporarySymbolId, line, column, sourceId, "
"locationKind) VALUES(?,?,?,?,?)",
database};
ReadStatement selectNewSourceIdsStatement{
"SELECT DISTINCT sourceId FROM newLocations WHERE NOT EXISTS (SELECT sourceId FROM sources "
"WHERE newLocations.sourceId == sources.sourceId)",
database};
WriteStatement addNewSymbolsToSymbolsStatement{
"INSERT INTO symbols(usr, symbolName, symbolKind) "
"SELECT usr, symbolName, symbolKind FROM newSymbols WHERE NOT EXISTS "
"(SELECT usr FROM symbols WHERE symbols.usr == newSymbols.usr)",
m_database
};
WriteStatement m_syncNewSymbolsFromSymbolsStatement{
"UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = symbols.usr)",
m_database
};
WriteStatement m_syncSymbolsIntoNewLocationsStatement{
"UPDATE newLocations SET symbolId = (SELECT symbolId FROM newSymbols WHERE newSymbols.temporarySymbolId = newLocations.temporarySymbolId)",
m_database
};
WriteStatement m_deleteAllLocationsFromUpdatedFilesStatement{
database};
WriteStatement syncNewSymbolsFromSymbolsStatement{
"UPDATE newSymbols SET symbolId = (SELECT symbolId FROM symbols WHERE newSymbols.usr = "
"symbols.usr)",
database};
WriteStatement syncSymbolsIntoNewLocationsStatement{
"UPDATE newLocations SET symbolId = (SELECT symbolId FROM newSymbols WHERE "
"newSymbols.temporarySymbolId = newLocations.temporarySymbolId)",
database};
WriteStatement deleteAllLocationsFromUpdatedFilesStatement{
"DELETE FROM locations WHERE sourceId IN (SELECT DISTINCT sourceId FROM newLocations)",
m_database
};
WriteStatement m_insertNewLocationsInLocationsStatement{
"INSERT INTO locations(symbolId, line, column, sourceId, locationKind) SELECT symbolId, line, column, sourceId, locationKind FROM newLocations",
m_database
};
WriteStatement m_deleteNewSymbolsTableStatement{
"DELETE FROM newSymbols",
m_database
};
WriteStatement m_deleteNewLocationsTableStatement{
"DELETE FROM newLocations",
m_database
};
WriteStatement m_insertOrUpdateProjectPartStatement{
"INSERT INTO projectParts(projectPartName, toolChainArguments, compilerMacros, "
"systemIncludeSearchPaths, projectIncludeSearchPaths, language, languageVersion, "
"languageExtension) VALUES (?001,?002,?003,?004,?005,?006,?007,?008) ON "
"CONFLICT(projectPartName) DO UPDATE SET toolChainArguments=?002, compilerMacros=?003, "
"systemIncludeSearchPaths=?004, projectIncludeSearchPaths=?005, language=?006, "
"languageVersion=?007, languageExtension=?008",
m_database};
mutable ReadStatement m_getProjectPartIdStatement{
"SELECT projectPartId FROM projectParts WHERE projectPartName = ?",
m_database
};
mutable ReadStatement m_getCompileArgumentsForFileIdStatement{
"SELECT toolChainArguments FROM projectParts WHERE projectPartId = (SELECT projectPartId "
"FROM projectPartsSources WHERE sourceId = ?)",
m_database};
mutable ReadStatement m_getProjectPartArtefactsBySourceId{
"SELECT toolChainArguments, compilerMacros, systemIncludeSearchPaths, "
"projectIncludeSearchPaths, projectPartId, language, languageVersion, languageExtension "
"FROM projectParts WHERE projectPartId = (SELECT "
"projectPartId FROM projectPartsSources WHERE sourceId = ?)",
m_database};
mutable ReadStatement m_getProjectPartArtefactsByProjectPartName{
"SELECT toolChainArguments, compilerMacros, systemIncludeSearchPaths, "
"projectIncludeSearchPaths, projectPartId, language, languageVersion, languageExtension "
"FROM projectParts WHERE projectPartName = ?",
m_database};
database};
WriteStatement insertNewLocationsInLocationsStatement{
"INSERT INTO locations(symbolId, line, column, sourceId, locationKind) SELECT symbolId, "
"line, column, sourceId, locationKind FROM newLocations",
database};
WriteStatement deleteNewSymbolsTableStatement{"DELETE FROM newSymbols", database};
WriteStatement deleteNewLocationsTableStatement{"DELETE FROM newLocations", database};
};
} // namespace ClangBackEnd

View File

@@ -25,19 +25,13 @@
#pragma once
#include "filestatus.h"
#include "projectpartentry.h"
#include "projectpartartefact.h"
#include "sourcelocationentry.h"
#include "sourcedependency.h"
#include "symbolentry.h"
#include "usedmacro.h"
#include <includesearchpath.h>
#include <sqlitetransaction.h>
#include <compilermacro.h>
#include <sqlitetransaction.h>
#include <utils/cpplanguage_details.h>
namespace ClangBackEnd {
@@ -51,20 +45,6 @@ public:
virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
const SourceLocationEntries &sourceLocations)
= 0;
virtual int insertOrUpdateProjectPart(
Utils::SmallStringView projectPartName,
const Utils::SmallStringVector &commandLineArguments,
const CompilerMacros &compilerMacros,
const ClangBackEnd::IncludeSearchPaths &systemIncludeSearchPaths,
const ClangBackEnd::IncludeSearchPaths &projectIncludeSearchPaths,
Utils::Language language,
Utils::LanguageVersion languageVersion,
Utils::LanguageExtension languageExtension)
= 0;
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(
FilePathId sourceId) const = 0;
virtual Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(
Utils::SmallStringView projectPartName) const = 0;
protected:
~SymbolStorageInterface() = default;

View File

@@ -34,12 +34,13 @@
namespace {
using ClangBackEnd::BuildDependency;
using ClangBackEnd::BuildDependencies;
using ClangBackEnd::BuildDependency;
using ClangBackEnd::FilePathId;
using ClangBackEnd::FilePathIds;
using ClangBackEnd::SourceEntry;
using ClangBackEnd::ProjectPartId;
using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceEntry;
using ClangBackEnd::SourceType;
using ClangBackEnd::UsedMacro;
using ClangBackEnd::UsedMacros;
@@ -64,7 +65,7 @@ protected:
mockBuildDependenciesGenerator,
mockSqliteTransactionBackend};
ClangBackEnd::ProjectPartContainer projectPart1{
"ProjectPart1",
1,
{"--yi"},
{{"YI", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
@@ -75,7 +76,7 @@ protected:
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ClangBackEnd::ProjectPartContainer projectPart2{
"ProjectPart2",
2,
{"--er"},
{{"ER", "2", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
@@ -114,10 +115,7 @@ TEST_F(BuildDependenciesProvider, CreateCallsFetchDependSourcesFromStorageIfTime
InSequence s;
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockBuildDependenciesStorage,
fetchProjectPartId(TypedEq<Utils::SmallStringView>("ProjectPart1")))
.WillOnce(Return(11));
EXPECT_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, 11))
EXPECT_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, {1}))
.WillRepeatedly(Return(firstSources));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(firstSources)).WillRepeatedly(Return(true));
@@ -132,13 +130,10 @@ TEST_F(BuildDependenciesProvider, CreateCallsFetchDependSourcesFromStorageIfTime
TEST_F(BuildDependenciesProvider, FetchDependSourcesFromStorage)
{
ON_CALL(mockBuildDependenciesStorage,
fetchProjectPartId(TypedEq<Utils::SmallStringView>("ProjectPart2")))
.WillByDefault(Return(11));
ON_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, 11)).WillByDefault(Return(firstSources));
ON_CALL(mockBuildDependenciesStorage, fetchDependSources({3}, 11)).WillByDefault(Return(secondSources));
ON_CALL(mockBuildDependenciesStorage, fetchDependSources({4}, 11)).WillByDefault(Return(thirdSources));
ON_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, {2})).WillByDefault(Return(firstSources));
ON_CALL(mockBuildDependenciesStorage, fetchDependSources({3}, {2}))
.WillByDefault(Return(secondSources));
ON_CALL(mockBuildDependenciesStorage, fetchDependSources({4}, {2})).WillByDefault(Return(thirdSources));
ON_CALL(mockModifiedTimeChecker, isUpToDate(_)).WillByDefault(Return(true));
auto buildDependency = provider.create(projectPart2);
@@ -157,17 +152,14 @@ TEST_F(BuildDependenciesProvider, CreateCallsFetchDependSourcesFromGeneratorIfTi
InSequence s;
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockBuildDependenciesStorage,
fetchProjectPartId(TypedEq<Utils::SmallStringView>("ProjectPart1")))
.WillOnce(Return(11));
EXPECT_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, TypedEq<int>(11)))
EXPECT_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, TypedEq<ProjectPartId>(1)))
.WillRepeatedly(Return(firstSources));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(firstSources)).WillRepeatedly(Return(false));
EXPECT_CALL(mockBuildDependenciesGenerator, create(projectPart1))
.WillOnce(Return(buildDependency));
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateSources(Eq(secondSources), 11));
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateSources(Eq(secondSources), {1}));
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateFileStatuses(Eq(fileStatuses)));
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateSourceDependencies(Eq(sourceDependencies)));
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateUsedMacros(Eq(secondUsedMacros)));
@@ -178,10 +170,7 @@ TEST_F(BuildDependenciesProvider, CreateCallsFetchDependSourcesFromGeneratorIfTi
TEST_F(BuildDependenciesProvider, FetchDependSourcesFromGenerator)
{
ON_CALL(mockBuildDependenciesStorage,
fetchProjectPartId(TypedEq<Utils::SmallStringView>("ProjectPart1")))
.WillByDefault(Return(11));
ON_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, 11)).WillByDefault(Return(firstSources));
ON_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, {1})).WillByDefault(Return(firstSources));
ON_CALL(mockModifiedTimeChecker, isUpToDate(_)).WillByDefault(Return(false));
ON_CALL(mockBuildDependenciesGenerator, create(projectPart1)).WillByDefault(Return(buildDependency));
@@ -195,10 +184,7 @@ TEST_F(BuildDependenciesProvider, CreateCallsFetchUsedMacrosFromStorageIfTimeSta
InSequence s;
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockBuildDependenciesStorage,
fetchProjectPartId(TypedEq<Utils::SmallStringView>("ProjectPart1")))
.WillOnce(Return(11));
EXPECT_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, 11))
EXPECT_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, {1}))
.WillRepeatedly(Return(firstSources));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(firstSources)).WillRepeatedly(Return(true));
@@ -213,10 +199,7 @@ TEST_F(BuildDependenciesProvider, CreateCallsFetchUsedMacrosFromStorageIfTimeSta
TEST_F(BuildDependenciesProvider, FetchUsedMacrosFromStorageIfDependSourcesAreUpToDate)
{
ON_CALL(mockBuildDependenciesStorage,
fetchProjectPartId(TypedEq<Utils::SmallStringView>("ProjectPart1")))
.WillByDefault(Return(11));
ON_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, 11)).WillByDefault(Return(firstSources));
ON_CALL(mockBuildDependenciesStorage, fetchDependSources({2}, {1})).WillByDefault(Return(firstSources));
ON_CALL(mockModifiedTimeChecker, isUpToDate(firstSources)).WillByDefault(Return(true));
ON_CALL(mockBuildDependenciesStorage, fetchUsedMacros({1})).WillByDefault(Return(firstUsedMacros));
ON_CALL(mockBuildDependenciesStorage, fetchUsedMacros({2})).WillByDefault(Return(secondUsedMacros));

View File

@@ -35,14 +35,15 @@
namespace {
using Utils::PathString;
using ClangBackEnd::FilePathId;
using ClangBackEnd::FilePathCachingInterface;
using ClangBackEnd::FilePathId;
using ClangBackEnd::ProjectPartId;
using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceType;
using ClangBackEnd::UsedMacro;
using Sqlite::Database;
using Sqlite::Table;
using Utils::PathString;
using Storage = ClangBackEnd::BuildDependenciesStorage<MockSqliteDatabase>;
@@ -61,14 +62,14 @@ protected:
MockSqliteWriteStatement &deleteOutdatedSourceDependenciesStatement = storage.deleteOutdatedSourceDependenciesStatement;
MockSqliteWriteStatement &deleteNewSourceDependenciesStatement = storage.deleteNewSourceDependenciesStatement;
MockSqliteReadStatement &getLowestLastModifiedTimeOfDependencies = storage.getLowestLastModifiedTimeOfDependencies;
MockSqliteWriteStatement &insertOrUpdateProjectPartsSourcesStatement = storage.insertOrUpdateProjectPartsSourcesStatement;
MockSqliteWriteStatement &insertOrUpdateProjectPartsFilesStatement = storage.insertOrUpdateProjectPartsFilesStatement;
MockSqliteReadStatement &fetchSourceDependenciesStatement = storage.fetchSourceDependenciesStatement;
MockSqliteReadStatement &fetchProjectPartIdStatement = storage.fetchProjectPartIdStatement;
MockSqliteReadStatement &fetchUsedMacrosStatement = storage.fetchUsedMacrosStatement;
MockSqliteWriteStatement &insertProjectPartNameStatement = storage.insertProjectPartNameStatement;
MockSqliteWriteStatement &updatePchCreationTimeStampStatement = storage.updatePchCreationTimeStampStatement;
MockSqliteWriteStatement &deleteAllProjectPartsSourcesWithProjectPartNameStatement
= storage.deleteAllProjectPartsSourcesWithProjectPartNameStatement;
MockSqliteWriteStatement &deleteAllProjectPartsFilesWithProjectPartNameStatement
= storage.deleteAllProjectPartsFilesWithProjectPartNameStatement;
};
TEST_F(BuildDependenciesStorage, ConvertStringsToJson)
@@ -177,10 +178,10 @@ TEST_F(BuildDependenciesStorage, UpdateSources)
SourceEntries entries{{1, SourceType::TopProjectInclude, 10, ClangBackEnd::HasMissingIncludes::Yes},
{2, SourceType::TopSystemInclude, 20}};
EXPECT_CALL(deleteAllProjectPartsSourcesWithProjectPartNameStatement, write(TypedEq<int>(22)));
EXPECT_CALL(insertOrUpdateProjectPartsSourcesStatement,
EXPECT_CALL(deleteAllProjectPartsFilesWithProjectPartNameStatement, write(TypedEq<int>(22)));
EXPECT_CALL(insertOrUpdateProjectPartsFilesStatement,
write(TypedEq<int>(1), TypedEq<int>(22), TypedEq<uchar>(0), TypedEq<uchar>(1)));
EXPECT_CALL(insertOrUpdateProjectPartsSourcesStatement,
EXPECT_CALL(insertOrUpdateProjectPartsFilesStatement,
write(TypedEq<int>(2), TypedEq<int>(22), TypedEq<uchar>(1), TypedEq<uchar>(0)));
storage.insertOrUpdateSources(entries, 22);
@@ -191,50 +192,10 @@ TEST_F(BuildDependenciesStorage, UpdatePchCreationTimeStamp)
InSequence s;
EXPECT_CALL(mockDatabase, immediateBegin());
EXPECT_CALL(updatePchCreationTimeStampStatement,
write(TypedEq<long long>(101), TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(updatePchCreationTimeStampStatement, write(TypedEq<long long>(101), TypedEq<int>(1)));
EXPECT_CALL(mockDatabase, commit());
storage.updatePchCreationTimeStamp(101, "project1");
}
TEST_F(BuildDependenciesStorage, CallsFetchProjectIdWithNonExistingProjectPartName)
{
EXPECT_CALL(fetchProjectPartIdStatement,
valueReturnInt32(TypedEq<Utils::SmallStringView>("test")));
EXPECT_CALL(insertProjectPartNameStatement, write(TypedEq<Utils::SmallStringView>("test")));
storage.fetchProjectPartId("test");
}
TEST_F(BuildDependenciesStorage, CallsFetchProjectIdWithExistingProjectPart)
{
EXPECT_CALL(fetchProjectPartIdStatement, valueReturnInt32(TypedEq<Utils::SmallStringView>("test")))
.WillOnce(Return(Utils::optional<int>{20}));
EXPECT_CALL(insertProjectPartNameStatement, write(TypedEq<Utils::SmallStringView>("test"))).Times(0);
storage.fetchProjectPartId("test");
}
TEST_F(BuildDependenciesStorage, FetchProjectIdWithNonExistingProjectPartName)
{
ON_CALL(fetchProjectPartIdStatement, valueReturnInt32(TypedEq<Utils::SmallStringView>("test")))
.WillByDefault(Return(Utils::optional<int>{}));
ON_CALL(mockDatabase, lastInsertedRowId()).WillByDefault(Return(21));
int id = storage.fetchProjectPartId("test");
ASSERT_THAT(id, 21);
}
TEST_F(BuildDependenciesStorage, FetchProjectIdWithExistingProjectPartName)
{
ON_CALL(fetchProjectPartIdStatement, valueReturnInt32(TypedEq<Utils::SmallStringView>("test")))
.WillByDefault(Return(Utils::optional<int>{20}));
int id = storage.fetchProjectPartId("test");
ASSERT_THAT(id, 20);
storage.updatePchCreationTimeStamp(101, 1);
}
TEST_F(BuildDependenciesStorage, CallsFetchDependSources)

View File

@@ -734,7 +734,7 @@ TEST_F(BuildDependencyCollector, Create)
generatedFiles.update(
{{TESTDATA_DIR "/builddependencycollector/project/generated_file.h", "#pragma once"}});
ClangBackEnd::ProjectPartContainer projectPart{
"project1",
1,
{},
{},
{{TESTDATA_DIR "/builddependencycollector/system", 1, IncludeSearchPathType::System}},
@@ -885,7 +885,7 @@ TEST_F(BuildDependencyCollector, Clear)
using ClangBackEnd::IncludeSearchPathType;
ClangBackEnd::BuildDependencyCollector collector{filePathCache, generatedFiles, environment};
ClangBackEnd::ProjectPartContainer projectPart{
"project1",
1,
{},
{},
{{TESTDATA_DIR "/builddependencycollector/system", 1, IncludeSearchPathType::System}},

View File

@@ -43,12 +43,14 @@ using testing::SizeIs;
using testing::NiceMock;
using Watcher = ClangBackEnd::ClangPathWatcher<NiceMock<MockQFileSytemWatcher>, NiceMock<MockTimer>>;
using ClangBackEnd::WatcherEntry;
using ClangBackEnd::WatcherEntries;
using ClangBackEnd::FilePath;
using ClangBackEnd::FilePathView;
using ClangBackEnd::FilePathId;
using ClangBackEnd::FilePathIds;
using ClangBackEnd::FilePathView;
using ClangBackEnd::ProjectPartId;
using ClangBackEnd::ProjectPartIds;
using ClangBackEnd::WatcherEntries;
using ClangBackEnd::WatcherEntry;
class ClangPathWatcher : public testing::Test
{
@@ -66,15 +68,15 @@ protected:
NiceMock<MockClangPathWatcherNotifier> notifier;
Watcher watcher{filePathCache, &notifier};
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
Utils::SmallString id1{"id4"};
Utils::SmallString id2{"id2"};
Utils::SmallString id3{"id3"};
ProjectPartId id1{2};
ProjectPartId id2{3};
ProjectPartId id3{4};
FilePathView path1{"/path/path1"};
FilePathView path2{"/path/path2"};
QString path1QString = QString(path1.toStringView());
QString path2QString = QString(path2.toStringView());
FilePathIds pathIds = {1, 2};
std::vector<int> ids{watcher.idCache().stringIds({id1, id2, id3})};
ClangBackEnd::ProjectPartIds ids{id1, id2, id3};
WatcherEntry watcherEntry1{ids[0], pathIds[0]};
WatcherEntry watcherEntry2{ids[1], pathIds[0]};
WatcherEntry watcherEntry3{ids[0], pathIds[1]};
@@ -324,7 +326,7 @@ TEST_F(ClangPathWatcher, NotifyFileChange)
{
watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}));
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id1)));
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id1, id2)));
mockQFileSytemWatcher.fileChanged(path1QString);
}
@@ -333,7 +335,7 @@ TEST_F(ClangPathWatcher, TwoNotifyFileChanges)
{
watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5}));
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id2, id3, id1)));
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id1, id2, id3)));
mockQFileSytemWatcher.fileChanged(path2QString);
mockQFileSytemWatcher.fileChanged(path1QString);

View File

@@ -54,8 +54,8 @@ public:
}
public:
ClangBackEnd::PchTask emptyProjectInfo{"empty", {}, {}, {}, {}, {}, {}, {}};
ClangBackEnd::PchTask cppProjectInfo{"project1", {}, {}, {}, {}, {}, {}, {}};
ClangBackEnd::PchTask emptyProjectInfo{0, {}, {}, {}, {}, {}, {}, {}};
ClangBackEnd::PchTask cppProjectInfo{1, {}, {}, {}, {}, {}, {}, {}};
};
template <>
@@ -68,7 +68,7 @@ public:
}
public:
ClangBackEnd::ProjectPartContainer emptyProjectInfo{"empty",
ClangBackEnd::ProjectPartContainer emptyProjectInfo{0,
{},
{},
{},
@@ -78,7 +78,7 @@ public:
Utils::Language::Cxx,
Utils::LanguageVersion::CXX98,
Utils::LanguageExtension::None};
ClangBackEnd::ProjectPartContainer cppProjectInfo{"project1",
ClangBackEnd::ProjectPartContainer cppProjectInfo{1,
{},
{},
{},
@@ -145,7 +145,7 @@ TYPED_TEST(CommandLineBuilder, CHeader)
"c-header",
"-std=c11",
"-nostdinc",
toNativePath("/source/file.c").path()));
toNativePath("/source/file.c")));
}
TYPED_TEST(CommandLineBuilder, CSource)
@@ -163,7 +163,7 @@ TYPED_TEST(CommandLineBuilder, CSource)
"c",
"-std=c11",
"-nostdinc",
toNativePath("/source/file.c").path()));
toNativePath("/source/file.c")));
}
TYPED_TEST(CommandLineBuilder, ObjectiveCHeader)
@@ -182,7 +182,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCHeader)
"objective-c-header",
"-std=c11",
"-nostdinc",
toNativePath("/source/file.c").path()));
toNativePath("/source/file.c")));
}
TYPED_TEST(CommandLineBuilder, ObjectiveCSource)
@@ -201,7 +201,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCSource)
"objective-c",
"-std=c11",
"-nostdinc",
toNativePath("/source/file.c").path()));
toNativePath("/source/file.c")));
}
TYPED_TEST(CommandLineBuilder, CppHeader)
@@ -220,7 +220,7 @@ TYPED_TEST(CommandLineBuilder, CppHeader)
"-std=c++98",
"-nostdinc",
"-nostdinc++",
toNativePath("/source/file.cpp").path()));
toNativePath("/source/file.cpp")));
}
TYPED_TEST(CommandLineBuilder, CppSource)
@@ -239,7 +239,7 @@ TYPED_TEST(CommandLineBuilder, CppSource)
"-std=c++98",
"-nostdinc",
"-nostdinc++",
toNativePath("/source/file.cpp").path()));
toNativePath("/source/file.cpp")));
}
TYPED_TEST(CommandLineBuilder, ObjectiveCppHeader)
@@ -259,7 +259,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCppHeader)
"-std=c++98",
"-nostdinc",
"-nostdinc++",
toNativePath("/source/file.cpp").path()));
toNativePath("/source/file.cpp")));
}
TYPED_TEST(CommandLineBuilder, ObjectiveCppSource)
@@ -279,7 +279,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCppSource)
"-std=c++98",
"-nostdinc",
"-nostdinc++",
toNativePath("/source/file.cpp").path()));
toNativePath("/source/file.cpp")));
}
TYPED_TEST(CommandLineBuilder, Cpp98)
@@ -514,18 +514,18 @@ TYPED_TEST(CommandLineBuilder, IncludesOrder)
"-nostdinc",
"-nostdinc++",
"-I",
toNativePath("/include/foo").path(),
toNativePath("/include/foo"),
"-I",
toNativePath("/include/bar").path(),
toNativePath("/include/bar"),
"-F",
toNativePath("/system/foo").path(),
toNativePath("/system/foo"),
"-isystem",
toNativePath("/system/bar").path(),
toNativePath("/system/bar"),
"-isystem",
toNativePath("/builtin/foo").path(),
toNativePath("/builtin/foo"),
"-isystem",
toNativePath("/builtin/bar").path(),
toNativePath("/source/file.cpp").path()));
toNativePath("/builtin/bar"),
toNativePath("/source/file.cpp")));
}
TYPED_TEST(CommandLineBuilder, EmptySourceFile)
@@ -556,7 +556,7 @@ TYPED_TEST(CommandLineBuilder, SourceFile)
"-std=c++98",
"-nostdinc",
"-nostdinc++",
toNativePath("/source/file.cpp").path()));
toNativePath("/source/file.cpp")));
}
@@ -573,7 +573,7 @@ TYPED_TEST(CommandLineBuilder, EmptyOutputFile)
"-std=c++98",
"-nostdinc",
"-nostdinc++",
toNativePath("/source/file.cpp").path()));
toNativePath("/source/file.cpp")));
}
TYPED_TEST(CommandLineBuilder, OutputFile)
@@ -594,8 +594,8 @@ TYPED_TEST(CommandLineBuilder, OutputFile)
"-nostdinc",
"-nostdinc++",
"-o",
toNativePath("/output/file.o").path(),
toNativePath("/source/file.cpp").path()));
toNativePath("/output/file.o"),
toNativePath("/source/file.cpp")));
}
TYPED_TEST(CommandLineBuilder, IncludePchPath)
@@ -619,10 +619,10 @@ TYPED_TEST(CommandLineBuilder, IncludePchPath)
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/pch/file.pch").path(),
toNativePath("/pch/file.pch"),
"-o",
toNativePath("/output/file.o").path(),
toNativePath("/source/file.cpp").path()));
toNativePath("/output/file.o"),
toNativePath("/source/file.cpp")));
}
TYPED_TEST(CommandLineBuilder, CompilerMacros)

View File

@@ -288,7 +288,7 @@ TEST_F(FilePathStorage, CallSelectAndWriteForFetchingSourceIdForUnknownEntry)
storage.fetchSourceId(5, "unknownfile.h");
}
TEST_F(FilePathStorage, RestartFetchDirectoryIDIfTheDatabaseIsBusyInBeginBecauseTheTableAlreadyChanged)
TEST_F(FilePathStorage, RestartFetchDirectoryIDIfTheStatementIsBusyInBeginBecauseTheTableAlreadyChanged)
{
InSequence s;
@@ -303,7 +303,8 @@ TEST_F(FilePathStorage, RestartFetchDirectoryIDIfTheDatabaseIsBusyInBeginBecause
storage.fetchDirectoryId("/other/unknow/path");
}
TEST_F(FilePathStorage, CallSelectAndWriteForFetchingDirectoryIdTwoTimesIfTheDatabaseIsBusyInWriteBecauseTheTableAlreadyChanged)
TEST_F(FilePathStorage,
CallSelectAndWriteForFetchingDirectoryIdTwoTimesIfTheStatementIsBusyInWriteBecauseTheTableAlreadyChanged)
{
InSequence s;
@@ -340,7 +341,7 @@ TEST_F(FilePathStorage, CallSelectAndWriteForFetchingDirectoryIdTwoTimesIfTheInd
storage.fetchDirectoryId("/other/unknow/path");
}
TEST_F(FilePathStorage, RestartFetchSourceIdIfTheDatabaseIsBusyInBeginBecauseTheTableAlreadyChanged)
TEST_F(FilePathStorage, RestartFetchSourceIdIfTheStatementIsBusyInBeginBecauseTheTableAlreadyChanged)
{
InSequence s;
@@ -356,7 +357,8 @@ TEST_F(FilePathStorage, RestartFetchSourceIdIfTheDatabaseIsBusyInBeginBecauseThe
storage.fetchSourceId(5, "otherunknownfile.h");
}
TEST_F(FilePathStorage, CallSelectAndWriteForFetchingSourceTwoTimesIfTheDatabaseIsBusyInWriteBecauseTheTableAlreadyChanged)
TEST_F(FilePathStorage,
CallSelectAndWriteForFetchingSourceTwoTimesIfTheStatementIsBusyInWriteBecauseTheTableAlreadyChanged)
{
InSequence s;
@@ -475,7 +477,7 @@ TEST_F(FilePathStorage, ThrowAsFetchingSourceNameForNonExistingId)
ASSERT_THROW(storage.fetchSourceNameAndDirectoryId(12), ClangBackEnd::SourceNameIdDoesNotExists);
}
TEST_F(FilePathStorage, RestartFetchSourceNameIfTheDatabaseIsBusyInBegin)
TEST_F(FilePathStorage, RestartFetchSourceNameIfTheStatementIsBusyInBegin)
{
InSequence s;
@@ -492,7 +494,7 @@ TEST_F(FilePathStorage, RestartFetchSourceNameIfTheDatabaseIsBusyInBegin)
storage.fetchSourceNameAndDirectoryId(42);
}
TEST_F(FilePathStorage, RestartFetchDirectoryPathIfTheDatabaseIsBusyInBegin)
TEST_F(FilePathStorage, RestartFetchDirectoryPathIfTheStatementIsBusyInBegin)
{
InSequence s;

View File

@@ -37,16 +37,16 @@ ClangBackEnd::NativeFilePath toNativePath(const char (&text)[Size])
return ClangBackEnd::NativeFilePath{path};
}
inline ClangBackEnd::NativeFilePath toNativePath(const QString &text)
inline Utils::PathString toNativePath(const QString &text)
{
ClangBackEnd::FilePath path{text};
return ClangBackEnd::NativeFilePath{path};
return ClangBackEnd::NativeFilePath{path}.path();
}
inline ClangBackEnd::NativeFilePath toNativePath(Utils::SmallStringView text)
inline Utils::PathString toNativePath(Utils::SmallStringView text)
{
ClangBackEnd::FilePath path{text};
return ClangBackEnd::NativeFilePath{path};
return ClangBackEnd::NativeFilePath{path}.path();
}

View File

@@ -48,6 +48,7 @@
#include <pchtask.h>
#include <precompiledheadersupdatedmessage.h>
#include <projectpartartefact.h>
#include <projectpartid.h>
#include <sourcedependency.h>
#include <sourcelocationentry.h>
#include <sourcelocationscontainer.h>
@@ -1022,10 +1023,10 @@ std::ostream &operator<<(std::ostream &out, const SourceDependency &sourceDepend
std::ostream &operator<<(std::ostream &out, const ProjectPartArtefact &projectPartArtefact)
{
return out << "("
<< projectPartArtefact.toolChainArguments << ", "
<< projectPartArtefact.compilerMacros
<<")";
return out << "(" << projectPartArtefact.projectPartId << ", "
<< projectPartArtefact.toolChainArguments << ", " << projectPartArtefact.compilerMacros
<< ", " << projectPartArtefact.language << ", " << projectPartArtefact.languageVersion
<< ", " << projectPartArtefact.languageExtension << ")";
}
std::ostream &operator<<(std::ostream &out, const CompilerMacro &compilerMacro)
@@ -1134,10 +1135,14 @@ std::ostream &operator<<(std::ostream &out, const SymbolIndexerTask &task)
const char* progressTypeToString(ClangBackEnd::ProgressType type)
{
switch (type) {
case ProgressType::Invalid: return "Invalid";
case ProgressType::PrecompiledHeader: return "PrecompiledHeader";
case ProgressType::Indexing: return "Indexing";
case ProgressType::DependencyCreation: return "DependencyCreation";
case ProgressType::Invalid:
return "Invalid";
case ProgressType::PrecompiledHeader:
return "PrecompiledHeader";
case ProgressType::Indexing:
return "Indexing";
case ProgressType::DependencyCreation:
return "Indexing";
}
return nullptr;
@@ -1265,6 +1270,11 @@ std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &containe
return out;
}
std::ostream &operator<<(std::ostream &out, const ProjectPartId &projectPathId)
{
return out << projectPathId.projectPathId;
}
void PrintTo(const FilePath &filePath, ::std::ostream *os)
{
*os << filePath;

View File

@@ -91,7 +91,7 @@ template <typename Type>
std::ostream &operator<<(std::ostream &out, const Utils::optional<Type> &optional)
{
if (optional)
return out << "optional" << optional.value();
return out << "optional " << optional.value();
else
return out << "empty optional()";
}
@@ -196,6 +196,7 @@ class IncludeSearchPath;
enum class IncludeSearchPathType : unsigned char;
struct ArgumentsEntry;
class ProjectPartContainer;
class ProjectPartId;
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
@@ -285,6 +286,7 @@ std::ostream &operator<<(std::ostream &out, const IncludeSearchPathType &pathTyp
std::ostream &operator<<(std::ostream &out, const IncludeSearchPath &path);
std::ostream &operator<<(std::ostream &out, const ArgumentsEntry &entry);
std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &container);
std::ostream &operator<<(std::ostream &out, const ProjectPartId &projectPathId);
void PrintTo(const FilePath &filePath, ::std::ostream *os);
void PrintTo(const FilePathView &filePathView, ::std::ostream *os);

View File

@@ -33,7 +33,8 @@ class MockBuildDependenciesStorage : public ClangBackEnd::BuildDependenciesStora
{
public:
MOCK_METHOD2(insertOrUpdateSources,
void(const ClangBackEnd::SourceEntries &sources, int projectPartId));
void(const ClangBackEnd::SourceEntries &sources,
ClangBackEnd::ProjectPartId projectPartId));
MOCK_METHOD1(insertOrUpdateUsedMacros,
void (const ClangBackEnd::UsedMacros &usedMacros));
MOCK_METHOD1(insertOrUpdateFileStatuses, void(const ClangBackEnd::FileStatuses &fileStatuses));
@@ -43,11 +44,12 @@ public:
long long (ClangBackEnd::FilePathId sourceId));
MOCK_CONST_METHOD2(fetchDependSources,
ClangBackEnd::SourceEntries(ClangBackEnd::FilePathId sourceId,
int projectPartId));
ClangBackEnd::ProjectPartId projectPartId));
MOCK_CONST_METHOD1(fetchUsedMacros,
ClangBackEnd::UsedMacros (ClangBackEnd::FilePathId sourceId));
MOCK_METHOD1(fetchProjectPartId, int(Utils::SmallStringView projectPartName));
MOCK_METHOD1(fetchProjectPartId,
ClangBackEnd::ProjectPartId(Utils::SmallStringView projectPartName));
MOCK_METHOD2(updatePchCreationTimeStamp,
void(long long pchCreationTimeStamp, Utils::SmallStringView projectPartName));
void(long long pchCreationTimeStamp, ClangBackEnd::ProjectPartId projectPartId));
};

View File

@@ -34,8 +34,7 @@ class MockClangPathWatcher : public ClangBackEnd::ClangPathWatcherInterface
public:
MOCK_METHOD1(updateIdPaths,
void (const std::vector<ClangBackEnd::IdPaths> &idPaths));
MOCK_METHOD1(removeIds,
void (const Utils::SmallStringVector &ids));
MOCK_METHOD1(removeIds, void(const ClangBackEnd::ProjectPartIds &ids));
MOCK_METHOD1(setNotifier,
void (ClangBackEnd::ClangPathWatcherNotifier *notifier));

View File

@@ -32,8 +32,7 @@
class MockClangPathWatcherNotifier : public ClangBackEnd::ClangPathWatcherNotifier
{
public:
MOCK_METHOD1(pathsWithIdsChanged,
void (const Utils::SmallStringVector &ids));
MOCK_METHOD1(pathsWithIdsChanged, void(const ClangBackEnd::ProjectPartIds &ids));
MOCK_METHOD1(pathsChanged,
void (const ClangBackEnd::FilePathIds &filePathIds));

View File

@@ -32,12 +32,13 @@
class MockPchManagerNotifier : public ClangPchManager::PchManagerNotifierInterface
{
public:
MockPchManagerNotifier(const ClangPchManager::PchManagerClient &pchManagerClient)
: ClangPchManager::PchManagerNotifierInterface(const_cast<ClangPchManager::PchManagerClient&>(pchManagerClient))
MockPchManagerNotifier(ClangPchManager::PchManagerClient &pchManagerClient)
: ClangPchManager::PchManagerNotifierInterface(pchManagerClient)
{}
MOCK_METHOD3(precompiledHeaderUpdated,
void (const QString &projectPartId, const QString &pchFilePath, long long lastModified));
MOCK_METHOD1(precompiledHeaderRemoved,
void (const QString &projectPartId));
void(ClangBackEnd::ProjectPartId projectPartId,
const QString &pchFilePath,
long long lastModified));
MOCK_METHOD1(precompiledHeaderRemoved, void(ClangBackEnd::ProjectPartId projectPartId));
};

View File

@@ -35,8 +35,7 @@ public:
MOCK_METHOD2(addProjectParts,
void(const ClangBackEnd::ProjectPartContainers &projectParts,
const Utils::SmallStringVector &toolChainArguments));
MOCK_METHOD1(removeProjectParts,
void (const Utils::SmallStringVector &projectsPartIds));
MOCK_METHOD1(removeProjectParts, void(const ClangBackEnd::ProjectPartIds &projectsPartIds));
void addProjectParts(ClangBackEnd::ProjectPartContainers &&projectParts,
Utils::SmallStringVector &&toolChainArguments) override

View File

@@ -34,7 +34,7 @@ class MockPchTaskQueue : public ClangBackEnd::PchTaskQueueInterface
public:
MOCK_METHOD1(addSystemPchTasks, void(const ClangBackEnd::PchTasks &pchTasks));
MOCK_METHOD1(addProjectPchTasks, void(const ClangBackEnd::PchTasks &pchTasks));
MOCK_METHOD1(removePchTasks, void(const Utils::SmallStringVector &projectsPartIds));
MOCK_METHOD1(removePchTasks, void(const ClangBackEnd::ProjectPartIds &projectsPartIds));
MOCK_METHOD0(processEntries, void ());
void addSystemPchTasks(ClangBackEnd::PchTasks &&pchTasks) override

View File

@@ -36,7 +36,7 @@ public:
void(const ClangBackEnd::PchTaskSets &pchTaskSets,
const Utils::SmallStringVector &toolChainArguments));
MOCK_METHOD1(removePchTasks, void(const Utils::SmallStringVector &projectPartIds));
MOCK_METHOD1(removePchTasks, void(const ClangBackEnd::ProjectPartIds &projectPartIds));
void mergeTasks(ClangBackEnd::PchTaskSets &&pchTaskSets,
Utils::SmallStringVector &&toolChainArguments) override

View File

@@ -33,18 +33,19 @@ class MockPrecompiledHeaderStorage : public ClangBackEnd::PrecompiledHeaderStora
{
public:
MOCK_METHOD3(insertProjectPrecompiledHeader,
void(Utils::SmallStringView projectPartName,
void(ClangBackEnd::ProjectPartId projectPartId,
Utils::SmallStringView pchPath,
long long pchBuildTime));
MOCK_METHOD1(deleteProjectPrecompiledHeader, void(Utils::SmallStringView projectPartName));
MOCK_METHOD1(deleteProjectPrecompiledHeader, void(ClangBackEnd::ProjectPartId projectPartId));
MOCK_METHOD3(insertSystemPrecompiledHeaders,
void(const Utils::SmallStringVector &projectPartNames,
void(const ClangBackEnd::ProjectPartIds &projectPartIds,
Utils::SmallStringView pchPath,
long long pchBuildTime));
MOCK_METHOD1(deleteSystemPrecompiledHeaders,
void(const Utils::SmallStringVector &projectPartNames));
void(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_METHOD1(fetchSystemPrecompiledHeaderPath,
ClangBackEnd::FilePath(Utils::SmallStringView projectPartName));
MOCK_CONST_METHOD1(fetchPrecompiledHeader,
Utils::optional<ClangBackEnd::ProjectPartPch>(int projectPartId));
ClangBackEnd::FilePath(ClangBackEnd::ProjectPartId projectPartId));
MOCK_CONST_METHOD1(
fetchPrecompiledHeader,
Utils::optional<ClangBackEnd::ProjectPartPch>(ClangBackEnd::ProjectPartId projectPartId));
};

View File

@@ -35,9 +35,10 @@ public:
MOCK_METHOD1(update,
ClangBackEnd::ProjectPartContainers(
const ClangBackEnd::ProjectPartContainers &projectsParts));
MOCK_METHOD1(remove, void(const Utils::SmallStringVector &projectPartIds));
MOCK_METHOD1(remove, void(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_CONST_METHOD1(
projects, ClangBackEnd::ProjectPartContainers(const Utils::SmallStringVector &projectPartIds));
projects,
ClangBackEnd::ProjectPartContainers(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_METHOD1(updateDeferred, void(const ClangBackEnd::ProjectPartContainers &projectsParts));
MOCK_METHOD0(deferredUpdates, ClangBackEnd::ProjectPartContainers());

View File

@@ -0,0 +1,60 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "googletest.h"
#include <projectpartsstorageinterface.h>
class MockProjectPartsStorage : public ClangBackEnd::ProjectPartsStorageInterface
{
public:
MOCK_CONST_METHOD0(fetchProjectParts, ClangBackEnd::ProjectPartContainers());
MOCK_CONST_METHOD1(
fetchProjectParts,
ClangBackEnd::ProjectPartContainers(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_CONST_METHOD1(fetchProjectPartId,
ClangBackEnd::ProjectPartId(Utils::SmallStringView projectPartName));
MOCK_CONST_METHOD1(fetchProjectPartName,
Utils::PathString(ClangBackEnd::ProjectPartId projectPartId));
MOCK_METHOD8(updateProjectPart,
void(ClangBackEnd::ProjectPartId projectPartId,
const Utils::SmallStringVector &commandLineArgument,
const ClangBackEnd::CompilerMacros &compilerMacros,
const ClangBackEnd::IncludeSearchPaths &systemIncludeSearchPaths,
const ClangBackEnd::IncludeSearchPaths &projectIncludeSearchPaths,
Utils::Language language,
Utils::LanguageVersion languageVersion,
Utils::LanguageExtension languageExtension));
MOCK_METHOD1(updateProjectParts, void(const ClangBackEnd::ProjectPartContainers &projectParts));
MOCK_CONST_METHOD1(
fetchProjectPartArtefact,
Utils::optional<ClangBackEnd::ProjectPartArtefact>(ClangBackEnd::FilePathId sourceId));
MOCK_CONST_METHOD1(fetchProjectPartArtefact,
Utils::optional<ClangBackEnd::ProjectPartArtefact>(
ClangBackEnd::ProjectPartId projectPartId));
MOCK_METHOD0(transactionBackend, Sqlite::TransactionInterface &());
};

View File

@@ -90,6 +90,13 @@ MockSqliteReadStatement::values<ClangBackEnd::UsedMacro, 2>(
return valuesReturnUsedMacros(reserveSize, sourceId);
}
template<>
FilePathIds MockSqliteReadStatement::values<ClangBackEnd::FilePathId>(std::size_t reserveSize,
const int &projectPartId)
{
return valuesReturnFilePathIds(reserveSize, projectPartId);
}
template <>
std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize)
{
@@ -116,6 +123,13 @@ MockSqliteReadStatement::value<int>(const Utils::PathString &text)
return valueReturnInt32(text);
}
template<>
Utils::optional<ClangBackEnd::ProjectPartId> MockSqliteReadStatement::value<ClangBackEnd::ProjectPartId>(
const Utils::SmallStringView &text)
{
return valueReturnProjectPartId(text);
}
template <>
Utils::optional<int>
MockSqliteReadStatement::value<int>(const int &directoryId, const Utils::SmallStringView &text)
@@ -144,9 +158,9 @@ MockSqliteReadStatement::value<Utils::PathString>(const Utils::SmallStringView &
return valueReturnPathString(path);
}
template <>
Utils::optional<ClangBackEnd::FilePath>
MockSqliteReadStatement::value<ClangBackEnd::FilePath>(const Utils::SmallStringView &path)
template<>
Utils::optional<ClangBackEnd::FilePath> MockSqliteReadStatement::value<ClangBackEnd::FilePath>(
const int &path)
{
return valueReturnFilePath(path);
}
@@ -165,9 +179,23 @@ MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 8>(const Utils
return valueReturnProjectPartArtefact(projectPartName);
}
template <>
template<>
Utils::optional<ClangBackEnd::ProjectPartContainer>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartContainer, 8>(const int &id)
{
return valueReturnProjectPartContainer(id);
}
template<>
ClangBackEnd::ProjectPartContainers MockSqliteReadStatement::values<ClangBackEnd::ProjectPartContainer,
8>(std::size_t reserveSize)
{
return valuesReturnProjectPartContainers(reserveSize);
}
template<>
Utils::optional<ClangBackEnd::ProjectPartPch>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartPch, 2>(const int &projectPartId)
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartPch, 3>(const int &projectPartId)
{
return valueReturnProjectPartPch(projectPartId);
}

View File

@@ -30,12 +30,13 @@
#include <sourcelocations.h>
#include <filepathstoragesources.h>
#include <stringcachefwd.h>
#include <projectpartartefact.h>
#include <projectpartcontainer.h>
#include <projectpartpch.h>
#include <sourceentry.h>
#include <usedmacro.h>
#include <stringcachefwd.h>
#include <symbol.h>
#include <usedmacro.h>
#include <cpptools/usages.h>
@@ -46,11 +47,12 @@
#include <tuple>
#include <vector>
using std::int64_t;
using ClangBackEnd::SourceEntry;
using ClangBackEnd::FilePathIds;
using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceEntry;
using ClangRefactoring::SourceLocation;
using ClangRefactoring::SourceLocations;
using std::int64_t;
namespace Sources = ClangBackEnd::Sources;
using ClangRefactoring::Symbol;
using ClangRefactoring::Symbols;
@@ -81,11 +83,11 @@ public:
MOCK_METHOD3(valuesReturnSourceEntries,
SourceEntries(std::size_t, int, int));
MOCK_METHOD2(valuesReturnUsedMacros,
UsedMacros (std::size_t, int));
MOCK_METHOD2(valuesReturnUsedMacros, UsedMacros(std::size_t, int));
MOCK_METHOD1(valueReturnInt32,
Utils::optional<int>(Utils::SmallStringView));
MOCK_METHOD2(valuesReturnFilePathIds, FilePathIds(std::size_t, int));
MOCK_METHOD1(valueReturnInt32, Utils::optional<int>(Utils::SmallStringView));
MOCK_METHOD2(valueReturnInt32,
Utils::optional<int>(int, Utils::SmallStringView));
@@ -99,8 +101,7 @@ public:
MOCK_METHOD1(valueReturnPathString,
Utils::optional<Utils::PathString>(Utils::SmallStringView));
MOCK_METHOD1(valueReturnFilePath,
Utils::optional<ClangBackEnd::FilePath>(Utils::SmallStringView));
MOCK_METHOD1(valueReturnFilePath, Utils::optional<ClangBackEnd::FilePath>(int));
MOCK_METHOD1(valueReturnSmallString,
Utils::optional<Utils::SmallString>(int));
@@ -113,7 +114,10 @@ public:
MOCK_METHOD1(valueReturnProjectPartArtefact,
Utils::optional<ClangBackEnd::ProjectPartArtefact>(Utils::SmallStringView));
MOCK_METHOD1(valuesReturnProjectPartArtefacts, ClangBackEnd::ProjectPartArtefacts(std::size_t));
MOCK_METHOD1(valueReturnProjectPartContainer,
Utils::optional<ClangBackEnd::ProjectPartContainer>(int));
MOCK_METHOD1(valuesReturnProjectPartContainers, ClangBackEnd::ProjectPartContainers(std::size_t));
MOCK_METHOD1(valueReturnProjectPartPch,
Utils::optional<ClangBackEnd::ProjectPartPch>(int));
@@ -129,6 +133,9 @@ public:
MOCK_METHOD2(valueReturnSourceLocation,
SourceLocation(long long, int));
MOCK_METHOD1(valueReturnProjectPartId,
Utils::optional<ClangBackEnd::ProjectPartId>(Utils::SmallStringView));
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryType>
@@ -201,6 +208,10 @@ MockSqliteReadStatement::values<ClangBackEnd::UsedMacro, 2>(
std::size_t reserveSize,
const int &sourceId);
template<>
FilePathIds MockSqliteReadStatement::values<ClangBackEnd::FilePathId>(std::size_t reserveSize,
const int &projectPartId);
template <>
std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize);
@@ -215,9 +226,13 @@ template <>
Utils::optional<int>
MockSqliteReadStatement::value<int>(const Utils::PathString&);
template <>
Utils::optional<ClangBackEnd::FilePath>
MockSqliteReadStatement::value<ClangBackEnd::FilePath>(const Utils::SmallStringView&);
template<>
Utils::optional<ClangBackEnd::ProjectPartId> MockSqliteReadStatement::value<ClangBackEnd::ProjectPartId>(
const Utils::SmallStringView &);
template<>
Utils::optional<ClangBackEnd::FilePath> MockSqliteReadStatement::value<ClangBackEnd::FilePath>(
const int &);
template <>
Utils::optional<int>
@@ -243,9 +258,17 @@ template <>
Utils::optional<ClangBackEnd::ProjectPartArtefact>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 8>(const int&);
template <>
template<>
Utils::optional<ClangBackEnd::ProjectPartContainer>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartContainer, 8>(const int &);
template<>
ClangBackEnd::ProjectPartContainers MockSqliteReadStatement::values<ClangBackEnd::ProjectPartContainer,
8>(std::size_t reserveSize);
template<>
Utils::optional<ClangBackEnd::ProjectPartPch>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartPch, 2>(const int&);
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartPch, 3>(const int &);
template <>
Utils::optional<Utils::SmallString>

View File

@@ -65,8 +65,7 @@ public:
MOCK_METHOD2(write, void(Utils::SmallStringView, Utils::SmallStringView));
MOCK_METHOD3(write,
void (Utils::SmallStringView, Utils::SmallStringView, long long));
MOCK_METHOD3(write, void(int, Utils::SmallStringView, long long));
MOCK_METHOD3(write,
void (Utils::SmallStringView, Utils::SmallStringView, Utils::SmallStringView));
@@ -78,7 +77,7 @@ public:
Utils::SmallStringView));
MOCK_METHOD8(write,
void(Utils::SmallStringView,
void(int,
Utils::SmallStringView,
Utils::SmallStringView,
Utils::SmallStringView,

View File

@@ -37,17 +37,4 @@ public:
MOCK_METHOD2(addSymbolsAndSourceLocations,
void(const ClangBackEnd::SymbolEntries &symbolEentries,
const ClangBackEnd::SourceLocationEntries &sourceLocations));
MOCK_METHOD8(insertOrUpdateProjectPart,
int(Utils::SmallStringView projectPartName,
const Utils::SmallStringVector &commandLineArgument,
const ClangBackEnd::CompilerMacros &compilerMacros,
const ClangBackEnd::IncludeSearchPaths &systemIncludeSearchPaths,
const ClangBackEnd::IncludeSearchPaths &projectIncludeSearchPaths,
Utils::Language language,
Utils::LanguageVersion languageVersion,
Utils::LanguageExtension languageExtension));
MOCK_CONST_METHOD1(fetchProjectPartArtefact,
Utils::optional<ClangBackEnd::ProjectPartArtefact> (ClangBackEnd::FilePathId sourceId));
MOCK_CONST_METHOD1(fetchProjectPartArtefact,
Utils::optional<ClangBackEnd::ProjectPartArtefact> (Utils::SmallStringView projectPartName));
};

View File

@@ -105,7 +105,7 @@ protected:
mockClangPathWatcher,
mockBuildDependenciesStorage};
PchTask pchTask1{
"project1",
1,
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")},
@@ -149,11 +149,11 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArguments)
"-nostdinc",
"-nostdinc++",
"-I",
toNativePath(TESTDATA_DIR "/builddependencycollector/project").path(),
toNativePath(TESTDATA_DIR "/builddependencycollector/project"),
"-isystem",
toNativePath(TESTDATA_DIR "/builddependencycollector/external").path(),
toNativePath(TESTDATA_DIR "/builddependencycollector/external"),
"-isystem",
toNativePath(TESTDATA_DIR "/builddependencycollector/system").path(),
toNativePath(TESTDATA_DIR "/builddependencycollector/system"),
"-o",
"project.pch"));
}
@@ -174,11 +174,11 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArgumentsWithSystemPch)
"-nostdinc",
"-nostdinc++",
"-I",
toNativePath(TESTDATA_DIR "/builddependencycollector/project").path(),
toNativePath(TESTDATA_DIR "/builddependencycollector/project"),
"-isystem",
toNativePath(TESTDATA_DIR "/builddependencycollector/external").path(),
toNativePath(TESTDATA_DIR "/builddependencycollector/external"),
"-isystem",
toNativePath(TESTDATA_DIR "/builddependencycollector/system").path(),
toNativePath(TESTDATA_DIR "/builddependencycollector/system"),
"-Xclang",
"-include-pch",
"-Xclang",
@@ -205,7 +205,7 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterSucess)
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, "project1"),
Field(&ClangBackEnd::IdPaths::id, 1),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
@@ -224,7 +224,7 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreNotWatchedAfterFail)
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(
ElementsAre(AllOf(Field(&ClangBackEnd::IdPaths::id, "project1"),
ElementsAre(AllOf(Field(&ClangBackEnd::IdPaths::id, 1),
Field(&ClangBackEnd::IdPaths::filePathIds, IsEmpty())))));
creator.doInMainThreadAfterFinished();
@@ -234,7 +234,7 @@ TEST_F(PchCreatorVerySlowTest, PchCreationTimeStampsAreUpdated)
{
creator.generatePch(std::move(pchTask1));
EXPECT_CALL(mockBuildDependenciesStorage, updatePchCreationTimeStamp(_, Eq("project1")));
EXPECT_CALL(mockBuildDependenciesStorage, updatePchCreationTimeStamp(_, Eq(1)));
creator.doInMainThreadAfterFinished();
}
@@ -244,7 +244,7 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchForCreatesPchForPchTask)
creator.generatePch(std::move(pchTask1));
ASSERT_THAT(creator.projectPartPch(),
AllOf(Field(&ProjectPartPch::projectPartId, Eq("project1")),
AllOf(Field(&ProjectPartPch::projectPartId, Eq(1)),
Field(&ProjectPartPch::pchPath, Not(IsEmpty())),
Field(&ProjectPartPch::lastModified, Not(Eq(-1)))));
}
@@ -255,7 +255,7 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchCleared)
creator.clear();
ASSERT_THAT(creator.projectPartPch(), ClangBackEnd::ProjectPartPch{});
ASSERT_FALSE(creator.projectPartPch().isValid());
}
TEST_F(PchCreatorVerySlowTest, SourcesCleared)
@@ -278,7 +278,8 @@ TEST_F(PchCreatorVerySlowTest, ClangToolCleared)
TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesFaultyPchForPchTask)
{
PchTask faultyPchTask{"faultyProjectPart",
PchTask faultyPchTask{
0,
{id(TESTDATA_DIR "/builddependencycollector/project/faulty.cpp")},
{},
{{"DEFINE", "1", 1}},
@@ -290,7 +291,7 @@ TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesFaultyPchForPchTask
creator.generatePch(std::move(faultyPchTask));
ASSERT_THAT(creator.projectPartPch(),
AllOf(Field(&ProjectPartPch::projectPartId, Eq("faultyProjectPart")),
AllOf(Field(&ProjectPartPch::projectPartId, Eq(0)),
Field(&ProjectPartPch::pchPath, IsEmpty()),
Field(&ProjectPartPch::lastModified, Gt(0))));
}

View File

@@ -29,6 +29,7 @@
#include "mockpchmanagerserver.h"
#include "mockprecompiledheaderstorage.h"
#include "mockprogressmanager.h"
#include "mockprojectpartsstorage.h"
#include <pchmanagerclient.h>
#include <pchmanagerprojectupdater.h>
@@ -46,10 +47,6 @@ namespace {
using ClangBackEnd::PrecompiledHeadersUpdatedMessage;
using testing::_;
using testing::Contains;
using testing::Not;
class PchManagerClient : public ::testing::Test
{
protected:
@@ -58,17 +55,21 @@ protected:
ClangPchManager::PchManagerClient client{mockPchCreationProgressManager,
mockDependencyCreationProgressManager};
NiceMock<MockPchManagerServer> mockPchManagerServer;
NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
NiceMock<MockPchManagerNotifier> mockPchManagerNotifier{client};
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
ClangBackEnd::FilePathCaching filePathCache{database};
ClangPchManager::PchManagerProjectUpdater projectUpdater{mockPchManagerServer, client, filePathCache};
Utils::SmallString projectPartId{"projectPartId"};
ClangPchManager::PchManagerProjectUpdater projectUpdater{mockPchManagerServer,
client,
filePathCache,
mockProjectPartsStorage};
ClangBackEnd::ProjectPartId projectPartId{1};
ClangBackEnd::FilePath pchFilePath{"/path/to/pch"};
PrecompiledHeadersUpdatedMessage message{{{projectPartId.clone(), pchFilePath.clone(), 1}}};
Utils::SmallString projectPartId2{"projectPartId2"};
PrecompiledHeadersUpdatedMessage message{{{projectPartId, pchFilePath.clone(), 1}}};
ClangBackEnd::ProjectPartId projectPartId2{2};
ClangBackEnd::FilePath pchFilePath2{"/path/to/pch2"};
PrecompiledHeadersUpdatedMessage message2{{{projectPartId2.clone(), pchFilePath2.clone(), 1}}};
PrecompiledHeadersUpdatedMessage message2{{{projectPartId2, pchFilePath2.clone(), 1}}};
};
TEST_F(PchManagerClient, NotifierAttached)
@@ -92,23 +93,22 @@ TEST_F(PchManagerClient, NotifierDetached)
TEST_F(PchManagerClient, Update)
{
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderUpdated(projectPartId.toQString(), pchFilePath.toQString(), Eq(1)));
EXPECT_CALL(mockPchManagerNotifier,
precompiledHeaderUpdated(projectPartId, pchFilePath.toQString(), Eq(1)));
client.precompiledHeadersUpdated(message.clone());
}
TEST_F(PchManagerClient, Remove)
{
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId.toQString()))
.Times(2);
EXPECT_CALL(mockPchManagerNotifier, precompiledHeaderRemoved(projectPartId)).Times(2);
projectUpdater.removeProjectParts({QString(projectPartId.clone()),
QString(projectPartId.clone())});
projectUpdater.removeProjectParts({projectPartId, projectPartId});
}
TEST_F(PchManagerClient, GetNoProjectPartPchForWrongProjectPartId)
{
auto optional = client.projectPartPch("foo");
auto optional = client.projectPartPch(23);
ASSERT_FALSE(optional);
}
@@ -126,7 +126,7 @@ TEST_F(PchManagerClient, ProjectPartPchRemoved)
{
client.precompiledHeadersUpdated(std::move(message));
client.precompiledHeaderRemoved(QString(projectPartId));
client.precompiledHeaderRemoved(projectPartId);
ASSERT_FALSE(client.projectPartPch(projectPartId));
}
@@ -145,19 +145,17 @@ TEST_F(PchManagerClient, ProjectPartPchForProjectPartIdLastModified)
{
client.precompiledHeadersUpdated(std::move(message));
ASSERT_THAT(client.projectPartPch(projectPartId).value().lastModified,
1);
ASSERT_THAT(client.projectPartPch(projectPartId)->lastModified, 1);
}
TEST_F(PchManagerClient, ProjectPartPchForProjectPartIdIsUpdated)
{
client.precompiledHeadersUpdated(message.clone());
PrecompiledHeadersUpdatedMessage updateMessage{{{projectPartId.clone(), pchFilePath.clone(), 42}}};
PrecompiledHeadersUpdatedMessage updateMessage{{{projectPartId, pchFilePath.clone(), 42}}};
client.precompiledHeadersUpdated(updateMessage.clone());
ASSERT_THAT(client.projectPartPch(projectPartId).value().lastModified,
42);
ASSERT_THAT(client.projectPartPch(projectPartId)->lastModified, 42);
}
TEST_F(PchManagerClient, SetPchCreationProgress)

View File

@@ -97,8 +97,7 @@ TEST_F(PchManagerClientServerInProcess, SendAliveMessage)
TEST_F(PchManagerClientServerInProcess, SendUpdateProjectPartsMessage)
{
ProjectPartContainer projectPart2{
"projectPartId",
ProjectPartContainer projectPart{1,
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
@@ -108,7 +107,7 @@ TEST_F(PchManagerClientServerInProcess, SendUpdateProjectPartsMessage)
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
UpdateProjectPartsMessage message{{projectPart2}, {"-m32"}};
UpdateProjectPartsMessage message{{projectPart}, {"-m32"}};
EXPECT_CALL(mockPchManagerServer, updateProjectParts(message));
@@ -129,7 +128,7 @@ TEST_F(PchManagerClientServerInProcess, SendUpdateGeneratedFilesMessage)
TEST_F(PchManagerClientServerInProcess, SendRemoveProjectPartsMessage)
{
RemoveProjectPartsMessage message{{"projectPartId1", "projectPartId2"}};
RemoveProjectPartsMessage message{{1, 2}};
EXPECT_CALL(mockPchManagerServer, removeProjectParts(message));
@@ -149,8 +148,7 @@ TEST_F(PchManagerClientServerInProcess, SendRemoveGeneratedFilesMessage)
TEST_F(PchManagerClientServerInProcess, SendPrecompiledHeaderUpdatedMessage)
{
PrecompiledHeadersUpdatedMessage message{{{"projectPartId", "/path/to/pch", 1}}};
PrecompiledHeadersUpdatedMessage message{{{1, "/path/to/pch", 1}}};
EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(message));

View File

@@ -28,7 +28,7 @@
#include "mockclangpathwatcher.h"
#include "mockpchmanagerclient.h"
#include "mockpchtaskgenerator.h"
#include "mockprojectparts.h"
#include "mockprojectpartsmanager.h"
#include "mockgeneratedfiles.h"
#include <filepathcaching.h>
@@ -77,15 +77,15 @@ protected:
mockProjectPartsManager,
mockGeneratedFiles};
NiceMock<MockPchManagerClient> mockPchManagerClient;
SmallString projectPartId1 = "project1";
SmallString projectPartId2 = "project2";
ClangBackEnd::ProjectPartId projectPartId1{1};
ClangBackEnd::ProjectPartId projectPartId2{2};
PathString main1Path = TESTDATA_DIR "/BuildDependencyCollector_main3.cpp";
PathString main2Path = TESTDATA_DIR "/BuildDependencyCollector_main2.cpp";
PathString header1Path = TESTDATA_DIR "/BuildDependencyCollector_header1.h";
PathString header2Path = TESTDATA_DIR "/BuildDependencyCollector_header2.h";
ClangBackEnd::IdPaths idPath{projectPartId1, {1, 2}};
ProjectPartContainer projectPart1{
projectPartId1.clone(),
projectPartId1,
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
@@ -96,7 +96,7 @@ protected:
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer projectPart2{
projectPartId2.clone(),
projectPartId2,
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
@@ -111,8 +111,8 @@ protected:
FileContainer generatedFile{{"/path/to/", "file"}, "content", {}};
ClangBackEnd::UpdateProjectPartsMessage updateProjectPartsMessage{
Utils::clone(projectParts), {"toolChainArgument"}};
ClangBackEnd::RemoveProjectPartsMessage removeProjectPartsMessage{{projectPart1.projectPartId.clone(),
projectPart2.projectPartId.clone()}};
ClangBackEnd::RemoveProjectPartsMessage removeProjectPartsMessage{
{projectPart1.projectPartId, projectPart2.projectPartId}};
};
TEST_F(PchManagerServer, FilterProjectPartsAndSendThemToQueue)

View File

@@ -41,6 +41,7 @@ using ClangBackEnd::IncludeSearchPath;
using ClangBackEnd::IncludeSearchPathType;
using ClangBackEnd::PchTask;
using ClangBackEnd::PchTaskSet;
using ClangBackEnd::ProjectPartId;
using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceType;
using ClangBackEnd::UsedMacro;
@@ -57,7 +58,7 @@ protected:
mockPchTaskMerger,
progressCounter};
ClangBackEnd::ProjectPartContainer projectPart1{
"ProjectPart1",
1,
{"--yi"},
{{"YI", "1", 1},
{"QI", "7", 1},
@@ -97,7 +98,7 @@ TEST_F(PchTaskGenerator, AddProjectParts)
mergeTasks(
ElementsAre(AllOf(
Field(&PchTaskSet::system,
AllOf(Field(&PchTask::projectPartIds, ElementsAre("ProjectPart1")),
AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})),
Field(&PchTask::includes, ElementsAre(5)),
Field(&PchTask::sources, IsEmpty()),
Field(&PchTask::compilerMacros,
@@ -114,7 +115,7 @@ TEST_F(PchTaskGenerator, AddProjectParts)
Field(&PchTask::languageExtension, Eq(Utils::LanguageExtension::All)))),
AllOf(Field(
&PchTaskSet::project,
AllOf(Field(&PchTask::projectPartIds, ElementsAre("ProjectPart1")),
AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})),
Field(&PchTask::includes, ElementsAre(3)),
Field(&PchTask::sources, ElementsAre(1, 2, 3, 4, 5)),
Field(&PchTask::compilerMacros,
@@ -153,11 +154,9 @@ TEST_F(PchTaskGenerator, RemoveProjectParts)
{
ON_CALL(mockBuildDependenciesProvider, create(_)).WillByDefault(Return(buildDependency));
EXPECT_CALL(
mockPchTaskMerger,
removePchTasks(ElementsAre("project1", "project2")));
EXPECT_CALL(mockPchTaskMerger, removePchTasks(ElementsAre(ProjectPartId{1}, ProjectPartId{2})));
generator.removeProjectParts({"project1", "project2"});
generator.removeProjectParts({1, 2});
}
}

View File

@@ -61,7 +61,7 @@ protected:
IncludeSearchPaths projectIncludeSearchPaths{
{"/project/includes", 1, IncludeSearchPathType::User},
{"/other/project/includes", 2, IncludeSearchPathType::User}};
PchTask systemTask1{"ProjectPart1",
PchTask systemTask1{1,
{1, 2},
{1, 2},
{{"YI", "1", 1}, {"SAN", "3", 3}},
@@ -69,7 +69,7 @@ protected:
{"--yi"},
systemIncludeSearchPaths,
projectIncludeSearchPaths};
PchTask systemTask2{"ProjectPart2",
PchTask systemTask2{2,
{1, 2},
{1, 2},
{{"YI", "1", 1}, {"SAN", "3", 3}},
@@ -77,7 +77,7 @@ protected:
{"--yi"},
systemIncludeSearchPaths,
projectIncludeSearchPaths};
PchTask systemTask2b{"ProjectPart2",
PchTask systemTask2b{2,
{3, 4},
{3, 4},
{{"YI", "1", 1}, {"SAN", "3", 3}},
@@ -85,7 +85,7 @@ protected:
{"--yi"},
systemIncludeSearchPaths,
projectIncludeSearchPaths};
PchTask systemTask3{"ProjectPart3",
PchTask systemTask3{3,
{1, 2},
{1, 2},
{{"YI", "1", 1}, {"SAN", "3", 3}},
@@ -93,7 +93,7 @@ protected:
{"--yi"},
systemIncludeSearchPaths,
projectIncludeSearchPaths};
PchTask projectTask1{"ProjectPart1",
PchTask projectTask1{1,
{11, 12},
{11, 12},
{{"SE", "4", 4}, {"WU", "5", 5}},
@@ -101,7 +101,7 @@ protected:
{"--yi"},
systemIncludeSearchPaths,
projectIncludeSearchPaths};
PchTask projectTask2{"ProjectPart2",
PchTask projectTask2{2,
{11, 12},
{11, 12},
{{"SE", "4", 4}, {"WU", "5", 5}},
@@ -109,7 +109,7 @@ protected:
{"--yi"},
systemIncludeSearchPaths,
projectIncludeSearchPaths};
PchTask projectTask2b{"ProjectPart2",
PchTask projectTask2b{2,
{21, 22},
{11, 12},
{{"SE", "4", 4}, {"WU", "5", 5}},
@@ -117,7 +117,7 @@ protected:
{"--yi"},
systemIncludeSearchPaths,
projectIncludeSearchPaths};
PchTask projectTask3{"ProjectPart3",
PchTask projectTask3{3,
{21, 22},
{21, 22},
{{"SE", "4", 4}, {"WU", "5", 5}},
@@ -125,7 +125,7 @@ protected:
{"--yi"},
systemIncludeSearchPaths,
projectIncludeSearchPaths};
PchTask systemTask4{Utils::SmallStringVector{"ProjectPart1", "ProjectPart3"},
PchTask systemTask4{{1, 3},
{1, 2},
{1, 2},
{{"YI", "1", 1}, {"SAN", "3", 3}},
@@ -293,18 +293,17 @@ TEST_F(PchTaskQueue, CreateProjectTaskFromPchTask)
{
InSequence s;
MockPchCreator mockPchCreator;
ClangBackEnd::ProjectPartPch projectPartPch{"", "/path/to/pch", 99};
ClangBackEnd::ProjectPartPch projectPartPch{{}, "/path/to/pch", 99};
auto tasks = queue.createProjectTasks({projectTask1});
auto projectTask = projectTask1;
projectTask.systemPchPath = "/path/to/pch";
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchSystemPrecompiledHeaderPath(Eq("ProjectPart1")))
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchSystemPrecompiledHeaderPath(Eq(1)))
.WillOnce(Return(ClangBackEnd::FilePath{"/path/to/pch"}));
EXPECT_CALL(mockPchCreator, generatePch(Eq(projectTask)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockPrecompiledHeaderStorage,
insertProjectPrecompiledHeader(Eq("ProjectPart1"), Eq("/path/to/pch"), 99));
insertProjectPrecompiledHeader(Eq(1), Eq("/path/to/pch"), 99));
tasks.front()(mockPchCreator);
}
@@ -313,16 +312,16 @@ TEST_F(PchTaskQueue, DeleteProjectPchEntryInDatabaseIfNoPchIsGenerated)
{
InSequence s;
MockPchCreator mockPchCreator;
ClangBackEnd::ProjectPartPch projectPartPch{"", "", 0};
ClangBackEnd::ProjectPartPch projectPartPch{{}, "", 0};
auto tasks = queue.createProjectTasks({projectTask1});
auto projectTask = projectTask1;
projectTask.systemPchPath = "/path/to/pch";
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchSystemPrecompiledHeaderPath(Eq("ProjectPart1")))
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchSystemPrecompiledHeaderPath(Eq(1)))
.WillOnce(Return(ClangBackEnd::FilePath{"/path/to/pch"}));
EXPECT_CALL(mockPchCreator, generatePch(Eq(projectTask)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockPrecompiledHeaderStorage, deleteProjectPrecompiledHeader(Eq("ProjectPart1")));
EXPECT_CALL(mockPrecompiledHeaderStorage, deleteProjectPrecompiledHeader(Eq(1)));
tasks.front()(mockPchCreator);
}
@@ -338,15 +337,13 @@ TEST_F(PchTaskQueue, CreateSystemTaskFromPchTask)
{
InSequence s;
MockPchCreator mockPchCreator;
ClangBackEnd::ProjectPartPch projectPartPch{"", "/path/to/pch", 99};
ClangBackEnd::ProjectPartPch projectPartPch{{}, "/path/to/pch", 99};
auto tasks = queue.createSystemTasks({systemTask4});
EXPECT_CALL(mockPchCreator, generatePch(Eq(systemTask4)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockPrecompiledHeaderStorage,
insertSystemPrecompiledHeaders(UnorderedElementsAre("ProjectPart1", "ProjectPart3"),
Eq("/path/to/pch"),
99));
insertSystemPrecompiledHeaders(UnorderedElementsAre(1, 3), Eq("/path/to/pch"), 99));
tasks.front()(mockPchCreator);
}
@@ -355,13 +352,13 @@ TEST_F(PchTaskQueue, DeleteSystemPchEntryInDatabaseIfNoPchIsGenerated)
{
InSequence s;
MockPchCreator mockPchCreator;
ClangBackEnd::ProjectPartPch projectPartPch{"", "", 0};
ClangBackEnd::ProjectPartPch projectPartPch{{}, "", 0};
auto tasks = queue.createSystemTasks({systemTask4});
EXPECT_CALL(mockPchCreator, generatePch(Eq(systemTask4)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteSystemPrecompiledHeaders(UnorderedElementsAre("ProjectPart1", "ProjectPart3")));
deleteSystemPrecompiledHeaders(UnorderedElementsAre(1, 3)));
tasks.front()(mockPchCreator);
}

View File

@@ -52,7 +52,7 @@ protected:
protected:
NiceMock<MockPchTaskQueue> mockPchTaskQueue;
ClangBackEnd::PchTasksMerger merger{mockPchTaskQueue};
PchTask systemTask1{"ProjectPart1",
PchTask systemTask1{1,
{1, 2},
{1, 2, 3},
{{"YI", "1", 1}, {"SAN", "3", 3}},
@@ -63,7 +63,7 @@ protected:
{"/framework/path", 1, IncludeSearchPathType::System}},
{{"/to/path1", 1, IncludeSearchPathType::User},
{"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask projectTask1{"ProjectPart1",
PchTask projectTask1{1,
{11, 12},
{11, 12},
{{"SE", "4", 4}, {"WU", "5", 5}},
@@ -73,7 +73,7 @@ protected:
{"/builtin/path", 2, IncludeSearchPathType::BuiltIn}},
{{"/to/path1", 1, IncludeSearchPathType::User},
{"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask systemTask2{"ProjectPart2",
PchTask systemTask2{2,
{11, 12},
{11, 12, 13},
{{"SE", "4", 4}, {"WU", "5", 5}},
@@ -84,7 +84,7 @@ protected:
{"/framework/path", 1, IncludeSearchPathType::System}},
{{"/to/path1", 1, IncludeSearchPathType::User},
{"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask projectTask2{"ProjectPart2",
PchTask projectTask2{2,
{11, 12},
{11, 12},
{{"SE", "4", 4}, {"WU", "5", 5}},
@@ -95,7 +95,7 @@ protected:
{"/framework/path", 1, IncludeSearchPathType::System}},
{{"/to/path1", 1, IncludeSearchPathType::User},
{"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask systemTask3{"ProjectPart3",
PchTask systemTask3{3,
{1, 2},
{1, 2},
{{"YI", "2", 1}, {"SAN", "3", 3}},
@@ -147,9 +147,9 @@ TEST_F(PchTasksMerger, AddSystemOnlyOneTask)
TEST_F(PchTasksMerger, RemoveTasks)
{
EXPECT_CALL(mockPchTaskQueue, removePchTasks(ElementsAre("project1", "project2")));
EXPECT_CALL(mockPchTaskQueue, removePchTasks(ElementsAre(1, 2)));
merger.removePchTasks({"project1", "project2"});
merger.removePchTasks({1, 2});
}
TEST_F(PchTasksMerger, MergeMacros)
@@ -286,14 +286,14 @@ TEST_F(PchTasksMerger, MergeProjectIds)
{
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.projectPartIds, ElementsAre("ProjectPart1", "ProjectPart2"));
ASSERT_THAT(systemTask1.projectPartIds, ElementsAre(1, 2));
}
TEST_F(PchTasksMerger, DontMergeProjectIds)
{
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.projectPartIds, ElementsAre("ProjectPart1"));
ASSERT_THAT(systemTask1.projectPartIds, ElementsAre(1));
}
TEST_F(PchTasksMerger, MergeIncludeSearchPaths)

View File

@@ -42,13 +42,12 @@ class PrecompiledHeaderStorage : public testing::Test
protected:
NiceMock<MockSqliteDatabase> database;
Storage storage{database};
MockSqliteWriteStatement &insertProjectPartStatement = storage.m_insertProjectPartStatement;
MockSqliteWriteStatement &insertProjectPrecompiledHeaderStatement = storage.m_insertProjectPrecompiledHeaderStatement;
MockSqliteWriteStatement &deleteProjectPrecompiledHeaderStatement = storage.m_deleteProjectPrecompiledHeaderStatement;
MockSqliteWriteStatement &insertSystemPrecompiledHeaderStatement = storage.m_insertSystemPrecompiledHeaderStatement;
MockSqliteWriteStatement &deleteSystemPrecompiledHeaderStatement = storage.m_deleteSystemPrecompiledHeaderStatement;
MockSqliteReadStatement &fetchSystemPrecompiledHeaderPathStatement = storage.m_fetchSystemPrecompiledHeaderPathStatement;
MockSqliteReadStatement &getPrecompiledHeader = storage.m_getPrecompiledHeader;
MockSqliteWriteStatement &insertProjectPrecompiledHeaderStatement = storage.insertProjectPrecompiledHeaderStatement;
MockSqliteWriteStatement &deleteProjectPrecompiledHeaderStatement = storage.deleteProjectPrecompiledHeaderStatement;
MockSqliteWriteStatement &insertSystemPrecompiledHeaderStatement = storage.insertSystemPrecompiledHeaderStatement;
MockSqliteWriteStatement &deleteSystemPrecompiledHeaderStatement = storage.deleteSystemPrecompiledHeaderStatement;
MockSqliteReadStatement &fetchSystemPrecompiledHeaderPathStatement = storage.fetchSystemPrecompiledHeaderPathStatement;
MockSqliteReadStatement &getPrecompiledHeader = storage.getPrecompiledHeader;
};
TEST_F(PrecompiledHeaderStorage, UseTransaction)
@@ -66,14 +65,13 @@ TEST_F(PrecompiledHeaderStorage, InsertProjectPrecompiledHeader)
InSequence s;
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(insertProjectPartStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(insertProjectPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1"),
write(TypedEq<int>(1),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
EXPECT_CALL(database, commit());
storage.insertProjectPrecompiledHeader("project1", "/path/to/pch", 22);
storage.insertProjectPrecompiledHeader(1, "/path/to/pch", 22);
}
TEST_F(PrecompiledHeaderStorage, InsertProjectPrecompiledHeaderStatementIsBusy)
@@ -82,14 +80,13 @@ TEST_F(PrecompiledHeaderStorage, InsertProjectPrecompiledHeaderStatementIsBusy)
EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(insertProjectPartStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(insertProjectPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1"),
write(TypedEq<int>(1),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
EXPECT_CALL(database, commit());
storage.insertProjectPrecompiledHeader("project1", "/path/to/pch", 22);
storage.insertProjectPrecompiledHeader(1, "/path/to/pch", 22);
}
TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeader)
@@ -97,10 +94,10 @@ TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeader)
InSequence s;
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq<int>(1)));
EXPECT_CALL(database, commit());
storage.deleteProjectPrecompiledHeader("project1");
storage.deleteProjectPrecompiledHeader(1);
}
TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeaderStatementIsBusy)
@@ -109,10 +106,10 @@ TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeaderStatementIsBusy)
EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq<int>(1)));
EXPECT_CALL(database, commit());
storage.deleteProjectPrecompiledHeader("project1");
storage.deleteProjectPrecompiledHeader(1);
}
TEST_F(PrecompiledHeaderStorage, InsertSystemPrecompiledHeaders)
@@ -120,19 +117,17 @@ TEST_F(PrecompiledHeaderStorage, InsertSystemPrecompiledHeaders)
InSequence s;
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(insertProjectPartStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(insertSystemPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1"),
write(TypedEq<int>(1),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
EXPECT_CALL(insertProjectPartStatement, write(TypedEq<Utils::SmallStringView>("project2")));
EXPECT_CALL(insertSystemPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project2"),
write(TypedEq<int>(2),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
EXPECT_CALL(database, commit());
storage.insertSystemPrecompiledHeaders({"project1", "project2"}, "/path/to/pch", 22);
storage.insertSystemPrecompiledHeaders({1, 2}, "/path/to/pch", 22);
}
TEST_F(PrecompiledHeaderStorage, InsertSystemPrecompiledHeadersStatementIsBusy)
@@ -141,19 +136,17 @@ TEST_F(PrecompiledHeaderStorage, InsertSystemPrecompiledHeadersStatementIsBusy)
EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(insertProjectPartStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(insertSystemPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1"),
write(TypedEq<int>(1),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
EXPECT_CALL(insertProjectPartStatement, write(TypedEq<Utils::SmallStringView>("project2")));
EXPECT_CALL(insertSystemPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project2"),
write(TypedEq<int>(2),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
EXPECT_CALL(database, commit());
storage.insertSystemPrecompiledHeaders({"project1", "project2"}, "/path/to/pch", 22);
storage.insertSystemPrecompiledHeaders({1, 2}, "/path/to/pch", 22);
}
TEST_F(PrecompiledHeaderStorage, DeleteSystemPrecompiledHeaders)
@@ -161,13 +154,11 @@ TEST_F(PrecompiledHeaderStorage, DeleteSystemPrecompiledHeaders)
InSequence s;
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(deleteSystemPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(deleteSystemPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project2")));
EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq<int>(1)));
EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq<int>(2)));
EXPECT_CALL(database, commit());
storage.deleteSystemPrecompiledHeaders({"project1", "project2"});
storage.deleteSystemPrecompiledHeaders({1, 2});
}
TEST_F(PrecompiledHeaderStorage, DeleteSystemPrecompiledHeadersStatementIsBusy)
@@ -176,13 +167,11 @@ TEST_F(PrecompiledHeaderStorage, DeleteSystemPrecompiledHeadersStatementIsBusy)
EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(deleteSystemPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(deleteSystemPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project2")));
EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq<int>(1)));
EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq<int>(2)));
EXPECT_CALL(database, commit());
storage.deleteSystemPrecompiledHeaders({"project1", "project2"});
storage.deleteSystemPrecompiledHeaders({1, 2});
}
TEST_F(PrecompiledHeaderStorage, CompilePrecompiledHeaderStatements)
@@ -198,42 +187,38 @@ TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderCalls)
InSequence s;
EXPECT_CALL(database, deferredBegin());
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement,
valueReturnFilePath(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement, valueReturnFilePath(TypedEq<int>(1)));
EXPECT_CALL(database, commit());
storage.fetchSystemPrecompiledHeaderPath("project1");
storage.fetchSystemPrecompiledHeaderPath(1);
}
TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeader)
{
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement,
valueReturnFilePath(TypedEq<Utils::SmallStringView>("project1")))
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement, valueReturnFilePath(TypedEq<int>(1)))
.WillOnce(Return(ClangBackEnd::FilePath{"/path/to/pch"}));
auto path = storage.fetchSystemPrecompiledHeaderPath("project1");
auto path = storage.fetchSystemPrecompiledHeaderPath(1);
ASSERT_THAT(path, "/path/to/pch");
}
TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderReturnsEmptyPath)
{
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement,
valueReturnFilePath(TypedEq<Utils::SmallStringView>("project1")))
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement, valueReturnFilePath(TypedEq<int>(1)))
.WillOnce(Return(ClangBackEnd::FilePath{}));
auto path = storage.fetchSystemPrecompiledHeaderPath("project1");
auto path = storage.fetchSystemPrecompiledHeaderPath(1);
ASSERT_THAT(path, IsEmpty());
}
TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderReturnsNullOptional)
{
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement,
valueReturnFilePath(TypedEq<Utils::SmallStringView>("project1")))
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement, valueReturnFilePath(TypedEq<int>(1)))
.WillOnce(Return(Utils::optional<ClangBackEnd::FilePath>{}));
auto path = storage.fetchSystemPrecompiledHeaderPath("project1");
auto path = storage.fetchSystemPrecompiledHeaderPath(1);
ASSERT_THAT(path, IsEmpty());
}
@@ -247,7 +232,7 @@ TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderCallsValueInStatement)
TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeader)
{
ClangBackEnd::ProjectPartPch pch{"", "/path/to/pch", 131};
ClangBackEnd::ProjectPartPch pch{{}, "/path/to/pch", 131};
EXPECT_CALL(getPrecompiledHeader, valueReturnProjectPartPch(Eq(25))).WillRepeatedly(Return(pch));
auto precompiledHeader = storage.fetchPrecompiledHeader(25);

View File

@@ -1,230 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include <projectpartsmanager.h>
#include <projectpartcontainer.h>
namespace {
using testing::ElementsAre;
using testing::UnorderedElementsAre;
using testing::IsEmpty;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::FilePathId;
class ProjectParts : public testing::Test
{
protected:
ClangBackEnd::ProjectPartsManager projectParts;
FilePathId firstHeader{1};
FilePathId secondHeader{2};
FilePathId firstSource{11};
FilePathId secondSource{12};
FilePathId thirdSource{13};
ProjectPartContainer projectPartContainer1{
"id",
{"-DUNIX", "-O2"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{firstHeader, secondHeader},
{firstSource, secondSource},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer updatedProjectPartContainer1{
"id",
{"-DUNIX", "-O2"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{firstHeader, secondHeader},
{firstSource, secondSource, thirdSource},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer projectPartContainer2{
"id2",
{"-DUNIX", "-O2"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{firstHeader, secondHeader},
{firstSource, secondSource},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
};
TEST_F(ProjectParts, GetNoProjectPartsForAddingEmptyProjectParts)
{
auto updatedProjectParts = projectParts.update({});
ASSERT_THAT(updatedProjectParts, IsEmpty());
}
TEST_F(ProjectParts, GetProjectPartForAddingProjectPart)
{
auto updatedProjectParts = projectParts.update({projectPartContainer1});
ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, ProjectPartAdded)
{
projectParts.update({projectPartContainer1});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, FilteredProjectPartAdded)
{
projectParts.update({projectPartContainer1});
projectParts.update({projectPartContainer1});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, DoNotUpdateNotNewProjectPart)
{
projectParts.update({projectPartContainer1});
auto updatedProjectParts = projectParts.update({projectPartContainer1});
ASSERT_THAT(updatedProjectParts, IsEmpty());
}
TEST_F(ProjectParts, NoDuplicateProjectPartAfterUpdatingWithNotNewProjectPart)
{
projectParts.update({projectPartContainer1});
auto updatedProjectParts = projectParts.update({projectPartContainer1});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, MergeProjectParts)
{
projectParts.mergeProjectParts({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectParts, MergeProjectMultipleTimesParts)
{
projectParts.mergeProjectParts({projectPartContainer2});
projectParts.mergeProjectParts({projectPartContainer1});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectParts, GetNewProjectParts)
{
projectParts.mergeProjectParts({projectPartContainer2});
auto newProjectParts = projectParts.newProjectParts({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(newProjectParts, ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, GetUpdatedProjectPart)
{
projectParts.update({projectPartContainer1, projectPartContainer2});
auto updatedProjectParts = projectParts.update({updatedProjectPartContainer1});
ASSERT_THAT(updatedProjectParts, ElementsAre(updatedProjectPartContainer1));
}
TEST_F(ProjectParts, ProjectPartIsReplacedWithUpdatedProjectPart)
{
projectParts.update({projectPartContainer1, projectPartContainer2});
projectParts.update({updatedProjectPartContainer1});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(updatedProjectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectParts, Remove)
{
projectParts.update({projectPartContainer1, projectPartContainer2});
projectParts.remove({projectPartContainer1.projectPartId});
ASSERT_THAT(projectParts.projectParts(), ElementsAre(projectPartContainer2));
}
TEST_F(ProjectParts, GetProjectById)
{
projectParts.update({projectPartContainer1, projectPartContainer2});
auto projectPartContainers = projectParts.projects({projectPartContainer1.projectPartId});
ASSERT_THAT(projectPartContainers, ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, GetProjectsByIds)
{
projectParts.update({projectPartContainer1, projectPartContainer2});
auto projectPartContainers = projectParts.projects({projectPartContainer1.projectPartId, projectPartContainer2.projectPartId});
ASSERT_THAT(projectPartContainers, UnorderedElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectParts, UpdateDeferred)
{
auto projectPartContainers = projectParts.update({projectPartContainer1, projectPartContainer2});
projectParts.updateDeferred({projectPartContainer1});
ASSERT_THAT(projectParts.deferredUpdates(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectParts, NotUpdateDeferred)
{
auto projectPartContainers = projectParts.update({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(projectParts.deferredUpdates(), IsEmpty());
}
TEST_F(ProjectParts, UpdateDeferredCleansDeferredUpdates)
{
auto projectPartContainers = projectParts.update({projectPartContainer1, projectPartContainer2});
projectParts.updateDeferred({projectPartContainer1});
projectParts.deferredUpdates();
ASSERT_THAT(projectParts.deferredUpdates(), IsEmpty());
}
}

View File

@@ -0,0 +1,321 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include "mockprojectpartsstorage.h"
#include <projectpartsmanager.h>
#include <projectpartcontainer.h>
namespace {
using ClangBackEnd::FilePathId;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::ProjectPartContainers;
class ProjectPartsManager : public testing::Test
{
protected:
NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
ClangBackEnd::ProjectPartsManager manager{mockProjectPartsStorage};
FilePathId firstHeader{1};
FilePathId secondHeader{2};
FilePathId firstSource{11};
FilePathId secondSource{12};
FilePathId thirdSource{13};
ProjectPartContainer projectPartContainer1{
1,
{"-DUNIX", "-O2"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{firstHeader, secondHeader},
{firstSource, secondSource},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer updatedProjectPartContainer1{
1,
{"-DUNIX", "-O2"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{firstHeader, secondHeader},
{firstSource, secondSource, thirdSource},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer projectPartContainer2{
2,
{"-DUNIX", "-O2"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{firstHeader, secondHeader},
{firstSource, secondSource},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
};
TEST_F(ProjectPartsManager, GetNoProjectPartsForAddingEmptyProjectParts)
{
auto updatedProjectParts = manager.update({});
ASSERT_THAT(updatedProjectParts, IsEmpty());
}
TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPart)
{
auto updatedProjectParts = manager.update({projectPartContainer1});
ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer1));
}
TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPartWithProjectPartAlreadyInTheDatabase)
{
ON_CALL(mockProjectPartsStorage, fetchProjectParts(_))
.WillByDefault(Return(ProjectPartContainers{projectPartContainer1}));
auto updatedProjectParts = manager.update({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(updatedProjectParts, ElementsAre(projectPartContainer2));
}
TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPartWithOlderProjectPartAlreadyInTheDatabase)
{
ON_CALL(mockProjectPartsStorage, fetchProjectParts(_))
.WillByDefault(Return(ProjectPartContainers{projectPartContainer1}));
auto updatedProjectParts = manager.update({updatedProjectPartContainer1, projectPartContainer2});
ASSERT_THAT(updatedProjectParts, ElementsAre(updatedProjectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectPartsManager, ProjectPartAdded)
{
manager.update({projectPartContainer1});
ASSERT_THAT(manager.projectParts(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectPartsManager, ProjectPartAddedWithProjectPartAlreadyInTheDatabase)
{
ON_CALL(mockProjectPartsStorage, fetchProjectParts(_))
.WillByDefault(Return(ProjectPartContainers{projectPartContainer1}));
manager.update({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(manager.projectParts(), ElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectPartsManager, ProjectPartAddedWithOlderProjectPartAlreadyInTheDatabase)
{
ON_CALL(mockProjectPartsStorage, fetchProjectParts(_))
.WillByDefault(Return(ProjectPartContainers{projectPartContainer1}));
manager.update({updatedProjectPartContainer1, projectPartContainer2});
ASSERT_THAT(manager.projectParts(),
ElementsAre(updatedProjectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectPartsManager, FilteredProjectPartAdded)
{
manager.update({projectPartContainer1});
manager.update({projectPartContainer1});
ASSERT_THAT(manager.projectParts(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectPartsManager, DoNotUpdateNotNewProjectPart)
{
manager.update({projectPartContainer1});
auto updatedProjectParts = manager.update({projectPartContainer1});
ASSERT_THAT(updatedProjectParts, IsEmpty());
}
TEST_F(ProjectPartsManager, NoDuplicateProjectPartAfterUpdatingWithNotNewProjectPart)
{
manager.update({projectPartContainer1});
auto updatedProjectParts = manager.update({projectPartContainer1});
ASSERT_THAT(manager.projectParts(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectPartsManager, MergeProjectParts)
{
manager.mergeProjectParts({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(manager.projectParts(), ElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectPartsManager, MergeProjectMultipleTimesParts)
{
manager.mergeProjectParts({projectPartContainer2});
manager.mergeProjectParts({projectPartContainer1});
ASSERT_THAT(manager.projectParts(), ElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectPartsManager, GetNewProjectParts)
{
auto newProjectParts = manager.filterNewProjectParts({projectPartContainer1, projectPartContainer2},
{projectPartContainer2});
ASSERT_THAT(newProjectParts, ElementsAre(projectPartContainer1));
}
TEST_F(ProjectPartsManager, GetUpdatedProjectPart)
{
manager.update({projectPartContainer1, projectPartContainer2});
auto updatedProjectParts = manager.update({updatedProjectPartContainer1});
ASSERT_THAT(updatedProjectParts, ElementsAre(updatedProjectPartContainer1));
}
TEST_F(ProjectPartsManager, ProjectPartIsReplacedWithUpdatedProjectPart)
{
manager.update({projectPartContainer1, projectPartContainer2});
manager.update({updatedProjectPartContainer1});
ASSERT_THAT(manager.projectParts(),
ElementsAre(updatedProjectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectPartsManager, Remove)
{
manager.update({projectPartContainer1, projectPartContainer2});
manager.remove({projectPartContainer1.projectPartId});
ASSERT_THAT(manager.projectParts(), ElementsAre(projectPartContainer2));
}
TEST_F(ProjectPartsManager, GetProjectById)
{
manager.update({projectPartContainer1, projectPartContainer2});
auto projectPartContainers = manager.projects({projectPartContainer1.projectPartId});
ASSERT_THAT(projectPartContainers, ElementsAre(projectPartContainer1));
}
TEST_F(ProjectPartsManager, GetProjectsByIds)
{
manager.update({projectPartContainer1, projectPartContainer2});
auto projectPartContainers = manager.projects(
{projectPartContainer1.projectPartId, projectPartContainer2.projectPartId});
ASSERT_THAT(projectPartContainers, UnorderedElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectPartsManager, UpdateDeferred)
{
auto projectPartContainers = manager.update({projectPartContainer1, projectPartContainer2});
manager.updateDeferred({projectPartContainer1});
ASSERT_THAT(manager.deferredUpdates(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectPartsManager, NotUpdateDeferred)
{
auto projectPartContainers = manager.update({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(manager.deferredUpdates(), IsEmpty());
}
TEST_F(ProjectPartsManager, UpdateDeferredCleansDeferredUpdates)
{
auto projectPartContainers = manager.update({projectPartContainer1, projectPartContainer2});
manager.updateDeferred({projectPartContainer1});
manager.deferredUpdates();
ASSERT_THAT(manager.deferredUpdates(), IsEmpty());
}
TEST_F(ProjectPartsManager, UpdateCallsIfNewProjectPartIsAdded)
{
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectParts(ElementsAre(Eq(projectPartContainer1.projectPartId))));
EXPECT_CALL(mockProjectPartsStorage, updateProjectParts(ElementsAre(projectPartContainer1)));
manager.update({projectPartContainer1});
}
TEST_F(ProjectPartsManager, UpdateCallsNotUpdateProjectPartsInStorageIfNoNewerProjectPartsExists)
{
manager.update({projectPartContainer1});
EXPECT_CALL(mockProjectPartsStorage, updateProjectParts(ElementsAre(projectPartContainer1))).Times(0);
manager.update({projectPartContainer1});
}
TEST_F(ProjectPartsManager, UpdateCallsNotFetchProjectPartsInStorageIfNoNewerProjectPartsExists)
{
manager.update({projectPartContainer1});
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectParts(ElementsAre(Eq(projectPartContainer1.projectPartId))))
.Times(0);
manager.update({projectPartContainer1});
}
TEST_F(ProjectPartsManager, UpdateCallsIfOldProjectPartIsAdded)
{
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectParts(ElementsAre(Eq(projectPartContainer1.projectPartId))))
.WillRepeatedly(Return(ProjectPartContainers{projectPartContainer1}));
EXPECT_CALL(mockProjectPartsStorage, updateProjectParts(ElementsAre(projectPartContainer1))).Times(0);
manager.update({projectPartContainer1});
}
TEST_F(ProjectPartsManager, UpdateCallsIfUpdatedProjectPartIsAdded)
{
manager.update({projectPartContainer1});
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectParts(ElementsAre(Eq(projectPartContainer1.projectPartId))))
.WillRepeatedly(Return(ProjectPartContainers{projectPartContainer1}));
EXPECT_CALL(mockProjectPartsStorage,
updateProjectParts(ElementsAre(updatedProjectPartContainer1)));
manager.update({updatedProjectPartContainer1});
}
} // namespace

View File

@@ -0,0 +1,435 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include "mocksqlitedatabase.h"
#include <projectpartsstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
namespace {
using ClangBackEnd::FilePathId;
using ClangBackEnd::IncludeSearchPath;
using ClangBackEnd::IncludeSearchPaths;
using ClangBackEnd::IncludeSearchPathType;
using ClangBackEnd::ProjectPartId;
using ClangBackEnd::ProjectPartIds;
class Data
{
protected:
ClangBackEnd::ProjectPartContainer projectPart1{1,
{"-m32"},
{{"FOO", "1", 1}},
{{"/include", 1, IncludeSearchPathType::System}},
{{"/home/yi", 2, IncludeSearchPathType::User}},
{1, 2},
{3, 4},
Utils::Language::Cxx,
Utils::LanguageVersion::CXX14,
Utils::LanguageExtension::Microsoft};
ClangBackEnd::ProjectPartContainer projectPart2{2,
{"-m64"},
{{"BAR", "2", 1}},
{{"/usr/include", 1, IncludeSearchPathType::System}},
{{"/home/er", 2, IncludeSearchPathType::User}},
{5, 6},
{7, 8},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::Gnu};
};
class ProjectPartsStorage : public testing::Test, public Data
{
using Storage = ClangBackEnd::ProjectPartsStorage<MockSqliteDatabase>;
protected:
ProjectPartsStorage()
{
ON_CALL(fetchProjectPartByIdStatement, valueReturnProjectPartContainer(Eq(1)))
.WillByDefault(Return(projectPart1));
ON_CALL(fetchProjectPartByIdStatement, valueReturnProjectPartContainer(Eq(2)))
.WillByDefault(Return(projectPart2));
ON_CALL(fetchProjectPartsHeadersByIdStatement, valuesReturnFilePathIds(_, Eq(1)))
.WillByDefault(Return(projectPart1.headerPathIds));
ON_CALL(fetchProjectPartsHeadersByIdStatement, valuesReturnFilePathIds(_, Eq(2)))
.WillByDefault(Return(projectPart2.headerPathIds));
ON_CALL(fetchProjectPartsSourcesByIdStatement, valuesReturnFilePathIds(_, Eq(1)))
.WillByDefault(Return(projectPart1.sourcePathIds));
ON_CALL(fetchProjectPartsSourcesByIdStatement, valuesReturnFilePathIds(_, Eq(2)))
.WillByDefault(Return(projectPart2.sourcePathIds));
}
NiceMock<MockSqliteDatabase> mockDatabase;
Storage storage{mockDatabase};
MockSqliteReadStatement &fetchProjectPartIdStatement = storage.fetchProjectPartIdStatement;
MockSqliteWriteStatement &insertProjectPartNameStatement = storage.insertProjectPartNameStatement;
MockSqliteReadStatement &fetchProjectPartNameStatement = storage.fetchProjectPartNameStatement;
MockSqliteReadStatement &fetchProjectPartsStatement = storage.fetchProjectPartsStatement;
MockSqliteReadStatement &fetchProjectPartByIdStatement = storage.fetchProjectPartByIdStatement;
MockSqliteWriteStatement &updateProjectPartStatement = storage.updateProjectPartStatement;
MockSqliteReadStatement &getProjectPartArtefactsBySourceId = storage.getProjectPartArtefactsBySourceId;
MockSqliteReadStatement &getProjectPartArtefactsByProjectPartId = storage.getProjectPartArtefactsByProjectPartId;
MockSqliteWriteStatement &deleteProjectPartsHeadersByIdStatement = storage.deleteProjectPartsHeadersByIdStatement;
MockSqliteWriteStatement &deleteProjectPartsSourcesByIdStatement = storage.deleteProjectPartsSourcesByIdStatement;
MockSqliteWriteStatement &insertProjectPartsHeadersStatement = storage.insertProjectPartsHeadersStatement;
MockSqliteWriteStatement &insertProjectPartsSourcesStatement = storage.insertProjectPartsSourcesStatement;
MockSqliteReadStatement &fetchProjectPartsHeadersByIdStatement = storage.fetchProjectPartsHeadersByIdStatement;
MockSqliteReadStatement &fetchProjectPartsSourcesByIdStatement = storage.fetchProjectPartsSourcesByIdStatement;
IncludeSearchPaths systemIncludeSearchPaths{{"/includes", 1, IncludeSearchPathType::BuiltIn},
{"/other/includes", 2, IncludeSearchPathType::System}};
IncludeSearchPaths projectIncludeSearchPaths{{"/project/includes", 1, IncludeSearchPathType::User},
{"/other/project/includes",
2,
IncludeSearchPathType::User}};
Utils::SmallString systemIncludeSearchPathsText{R"([["/includes",1,2],["/other/includes",2,3]])"};
Utils::SmallString projectIncludeSearchPathsText{
R"([["/project/includes",1,1],["/other/project/includes",2,1]])"};
ClangBackEnd::ProjectPartArtefact artefact{R"(["-DFOO"])",
R"([["FOO","1",1]])",
systemIncludeSearchPathsText,
projectIncludeSearchPathsText,
74,
Utils::Language::Cxx,
Utils::LanguageVersion::CXX11,
Utils::LanguageExtension::None};
};
TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithNonExistingProjectPartName)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")));
EXPECT_CALL(insertProjectPartNameStatement, write(TypedEq<Utils::SmallStringView>("test")));
EXPECT_CALL(mockDatabase, commit());
storage.fetchProjectPartId("test");
}
TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithExistingProjectPart)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")))
.WillOnce(Return(Utils::optional<ProjectPartId>{20}));
EXPECT_CALL(insertProjectPartNameStatement, write(TypedEq<Utils::SmallStringView>("test"))).Times(0);
EXPECT_CALL(mockDatabase, commit());
storage.fetchProjectPartId("test");
}
TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithBusyDatabaset)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")));
EXPECT_CALL(insertProjectPartNameStatement, write(TypedEq<Utils::SmallStringView>("test")))
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")));
EXPECT_CALL(insertProjectPartNameStatement, write(TypedEq<Utils::SmallStringView>("test")));
EXPECT_CALL(mockDatabase, commit());
storage.fetchProjectPartId("test");
}
TEST_F(ProjectPartsStorage, FetchProjectIdWithNonExistingProjectPartName)
{
ON_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")))
.WillByDefault(Return(Utils::optional<ProjectPartId>{}));
ON_CALL(mockDatabase, lastInsertedRowId()).WillByDefault(Return(21));
auto id = storage.fetchProjectPartId("test");
ASSERT_THAT(id.projectPathId, 21);
}
TEST_F(ProjectPartsStorage, FetchProjectIdWithNonExistingProjectPartNameAndIsBusy)
{
InSequence s;
EXPECT_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")))
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")))
.WillOnce(Return(ClangBackEnd::ProjectPartId{21}));
ON_CALL(mockDatabase, lastInsertedRowId()).WillByDefault(Return(21));
auto id = storage.fetchProjectPartId("test");
ASSERT_THAT(id.projectPathId, 21);
}
TEST_F(ProjectPartsStorage, FetchProjectIdWithExistingProjectPartName)
{
ON_CALL(fetchProjectPartIdStatement,
valueReturnProjectPartId(TypedEq<Utils::SmallStringView>("test")))
.WillByDefault(Return(Utils::optional<ProjectPartId>{20}));
auto id = storage.fetchProjectPartId("test");
ASSERT_THAT(id.projectPathId, 20);
}
TEST_F(ProjectPartsStorage, FetchProjectPartName)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartNameStatement, valueReturnPathString(TypedEq<int>(12)))
.WillOnce(Return(Utils::optional<Utils::PathString>{"test"}));
EXPECT_CALL(mockDatabase, commit());
storage.fetchProjectPartName(12);
}
TEST_F(ProjectPartsStorage, FetchProjectPartNameStatementIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartNameStatement, valueReturnPathString(TypedEq<int>(12)))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartNameStatement, valueReturnPathString(TypedEq<int>(12)))
.WillOnce(Return(Utils::optional<Utils::PathString>{"test"}));
EXPECT_CALL(mockDatabase, commit());
storage.fetchProjectPartName(12);
}
TEST_F(ProjectPartsStorage, FetchProjectParts)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartsStatement, valuesReturnProjectPartContainers(4096));
EXPECT_CALL(mockDatabase, commit());
storage.fetchProjectParts();
}
TEST_F(ProjectPartsStorage, FetchProjectPartsByIds)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartByIdStatement, valueReturnProjectPartContainer(Eq(1)));
EXPECT_CALL(fetchProjectPartByIdStatement, valueReturnProjectPartContainer(Eq(2)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchProjectParts({1, 2});
}
TEST_F(ProjectPartsStorage, FetchProjectPartsByIdsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartByIdStatement, valueReturnProjectPartContainer(Eq(1)));
EXPECT_CALL(fetchProjectPartByIdStatement, valueReturnProjectPartContainer(Eq(2)))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchProjectPartByIdStatement, valueReturnProjectPartContainer(Eq(1)));
EXPECT_CALL(fetchProjectPartByIdStatement, valueReturnProjectPartContainer(Eq(2)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchProjectParts({1, 2});
}
TEST_F(ProjectPartsStorage, FetchProjectPartsByIdsHasMissingId)
{
auto projectParts = storage.fetchProjectParts({1, 2, 3});
ASSERT_THAT(projectParts, ElementsAre(projectPart1, projectPart2));
}
TEST_F(ProjectPartsStorage, ConvertStringsToJson)
{
Utils::SmallStringVector strings{"foo", "bar", "foo"};
auto jsonText = storage.toJson(strings);
ASSERT_THAT(jsonText, Eq("[\"foo\",\"bar\",\"foo\"]"));
}
TEST_F(ProjectPartsStorage, UpdateProjectParts)
{
InSequence sequence;
EXPECT_CALL(mockDatabase, immediateBegin());
EXPECT_CALL(updateProjectPartStatement,
write(TypedEq<int>(1),
TypedEq<Utils::SmallStringView>(R"(["-m32"])"),
TypedEq<Utils::SmallStringView>(R"([["FOO","1",1]])"),
TypedEq<Utils::SmallStringView>(R"([["/include",1,3]])"),
TypedEq<Utils::SmallStringView>(R"([["/home/yi",2,1]])"),
1,
35,
2));
EXPECT_CALL(deleteProjectPartsHeadersByIdStatement, write(TypedEq<int>(1)));
EXPECT_CALL(insertProjectPartsHeadersStatement, write(TypedEq<int>(1), TypedEq<int>(1)));
EXPECT_CALL(insertProjectPartsHeadersStatement, write(TypedEq<int>(1), TypedEq<int>(2)));
EXPECT_CALL(deleteProjectPartsSourcesByIdStatement, write(TypedEq<int>(1)));
EXPECT_CALL(insertProjectPartsSourcesStatement, write(TypedEq<int>(1), TypedEq<int>(3)));
EXPECT_CALL(insertProjectPartsSourcesStatement, write(TypedEq<int>(1), TypedEq<int>(4)));
EXPECT_CALL(updateProjectPartStatement,
write(TypedEq<int>(2),
TypedEq<Utils::SmallStringView>(R"(["-m64"])"),
TypedEq<Utils::SmallStringView>(R"([["BAR","2",1]])"),
TypedEq<Utils::SmallStringView>(R"([["/usr/include",1,3]])"),
TypedEq<Utils::SmallStringView>(R"([["/home/er",2,1]])"),
0,
2,
1));
EXPECT_CALL(deleteProjectPartsHeadersByIdStatement, write(TypedEq<int>(2)));
EXPECT_CALL(insertProjectPartsHeadersStatement, write(TypedEq<int>(2), TypedEq<int>(5)));
EXPECT_CALL(insertProjectPartsHeadersStatement, write(TypedEq<int>(2), TypedEq<int>(6)));
EXPECT_CALL(deleteProjectPartsSourcesByIdStatement, write(TypedEq<int>(2)));
EXPECT_CALL(insertProjectPartsSourcesStatement, write(TypedEq<int>(2), TypedEq<int>(7)));
EXPECT_CALL(insertProjectPartsSourcesStatement, write(TypedEq<int>(2), TypedEq<int>(8)));
EXPECT_CALL(mockDatabase, commit());
storage.updateProjectParts({projectPart1, projectPart2});
}
TEST_F(ProjectPartsStorage, UpdateProjectPartsIsBusy)
{
InSequence sequence;
EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, immediateBegin());
EXPECT_CALL(updateProjectPartStatement,
write(TypedEq<int>(1),
TypedEq<Utils::SmallStringView>(R"(["-m32"])"),
TypedEq<Utils::SmallStringView>(R"([["FOO","1",1]])"),
TypedEq<Utils::SmallStringView>(R"([["/include",1,3]])"),
TypedEq<Utils::SmallStringView>(R"([["/home/yi",2,1]])"),
1,
35,
2));
EXPECT_CALL(mockDatabase, commit());
storage.updateProjectParts({projectPart1});
}
TEST_F(ProjectPartsStorage, FetchProjectPartArtefactBySourceIdCallsValueInStatement)
{
EXPECT_CALL(getProjectPartArtefactsBySourceId, valueReturnProjectPartArtefact(1))
.WillRepeatedly(Return(artefact));
storage.fetchProjectPartArtefact(FilePathId{1});
}
TEST_F(ProjectPartsStorage, FetchProjectPartArtefactBySourceIdReturnArtefact)
{
EXPECT_CALL(getProjectPartArtefactsBySourceId, valueReturnProjectPartArtefact(1))
.WillRepeatedly(Return(artefact));
auto result = storage.fetchProjectPartArtefact(FilePathId{1});
ASSERT_THAT(result, Eq(artefact));
}
TEST_F(ProjectPartsStorage, FetchProjectPartArtefactByProjectPartIdCallsValueInStatement)
{
EXPECT_CALL(getProjectPartArtefactsByProjectPartId, valueReturnProjectPartArtefact(74))
.WillRepeatedly(Return(artefact));
storage.fetchProjectPartArtefact(ProjectPartId{74});
}
TEST_F(ProjectPartsStorage, FetchProjectPartArtefactByProjectPartIdReturnArtefact)
{
EXPECT_CALL(getProjectPartArtefactsByProjectPartId, valueReturnProjectPartArtefact(74))
.WillRepeatedly(Return(artefact));
auto result = storage.fetchProjectPartArtefact(ProjectPartId{74});
ASSERT_THAT(result, Eq(artefact));
}
class ProjectPartsStorageSlow : public testing::Test, public Data
{
using Storage = ClangBackEnd::ProjectPartsStorage<Sqlite::Database>;
protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
Storage storage{database};
};
TEST_F(ProjectPartsStorageSlow, FetchProjectPartName)
{
auto id = storage.fetchProjectPartId("test");
auto name = storage.fetchProjectPartName(id);
ASSERT_THAT(name, "test");
}
TEST_F(ProjectPartsStorageSlow, FetchNonExistingProjectPartName)
{
ASSERT_THROW(storage.fetchProjectPartName(ClangBackEnd::ProjectPartId{1}),
ClangBackEnd::ProjectPartDoesNotExists);
}
TEST_F(ProjectPartsStorageSlow, FetchProjectPartId)
{
auto first = storage.fetchProjectPartId("test");
auto second = storage.fetchProjectPartId("test");
ASSERT_THAT(first, Eq(second));
}
TEST_F(ProjectPartsStorageSlow, FetchProjectParts)
{
projectPart1.projectPartId = storage.fetchProjectPartId("project1");
projectPart2.projectPartId = storage.fetchProjectPartId("project2");
storage.updateProjectParts({projectPart1, projectPart2});
auto projectParts = storage.fetchProjectParts(
{projectPart1.projectPartId, projectPart2.projectPartId});
ASSERT_THAT(projectParts, ElementsAre(projectPart1, projectPart2));
}
} // namespace

Some files were not shown because too many files have changed in this diff Show More