diff --git a/src/libs/clangsupport/clangpathwatcher.h b/src/libs/clangsupport/clangpathwatcher.h index 1130b1ab292..5ce02458c43 100644 --- a/src/libs/clangsupport/clangpathwatcher.h +++ b/src/libs/clangsupport/clangpathwatcher.h @@ -1,4 +1,4 @@ -; /**************************************************************************** +/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ @@ -57,7 +57,7 @@ void set_greedy_intersection_call( class WatcherEntry { public: - ProjectPartId id; + ProjectChunkId id; DirectoryPathId directoryPathId; FilePathId filePathId; long long lastModified = -1; @@ -140,25 +140,6 @@ public: m_notifier = notifier; } - static std::vector idsFromIdPaths(const std::vector &idPaths) - { - std::vector ids; - ids.reserve(idPaths.size()); - - auto extractId = [] (const IdPaths &idPath) { - return idPath.id; - }; - - std::transform(idPaths.begin(), - idPaths.end(), - std::back_inserter(ids), - extractId); - - std::sort(ids.begin(), ids.end()); - - return ids; - } - std::size_t sizeOfIdPaths(const std::vector &idPaths) { auto sumSize = [] (std::size_t size, const IdPaths &idPath) { @@ -168,19 +149,19 @@ public: return std::accumulate(idPaths.begin(), idPaths.end(), std::size_t(0), sumSize); } - std::pair convertIdPathsToWatcherEntriesAndIds( + std::pair convertIdPathsToWatcherEntriesAndIds( const std::vector &idPaths) { WatcherEntries entries; entries.reserve(sizeOfIdPaths(idPaths)); - ProjectPartIds ids; + ProjectChunkIds ids; ids.reserve(ids.size()); auto outputIterator = std::back_inserter(entries); for (const IdPaths &idPath : idPaths) { - ProjectPartId id = idPath.id; + ProjectChunkId id = idPath.id; ids.push_back(id); @@ -214,7 +195,7 @@ public: m_fileSystemWatcher.addPaths(convertWatcherEntriesToDirectoryPathList(filteredPaths)); } - void removeUnusedEntries(const WatcherEntries &entries, const ProjectPartIds &ids) + void removeUnusedEntries(const WatcherEntries &entries, const ProjectChunkIds &ids) { auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids); @@ -294,7 +275,7 @@ public: } WatcherEntries notAnymoreWatchedEntriesWithIds(const WatcherEntries &newEntries, - const ProjectPartIds &ids) const + const ProjectChunkIds &ids) const { auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less()); @@ -420,25 +401,22 @@ public: return filePathIds; } - ProjectPartIds idsForWatcherEntries(const WatcherEntries &foundEntries) + std::vector idPathsForWatcherEntries(WatcherEntries &&foundEntries) { - ProjectPartIds ids; - ids.reserve(foundEntries.size()); + std::sort(foundEntries.begin(), foundEntries.end(), [](WatcherEntry first, WatcherEntry second) { + return std::tie(first.id, first.filePathId) < std::tie(second.id, second.filePathId); + }); - std::transform(foundEntries.begin(), - foundEntries.end(), - std::back_inserter(ids), - [&](WatcherEntry entry) { return entry.id; }); + std::vector idPaths; + idPaths.reserve(foundEntries.size()); - return ids; - } + for (WatcherEntry entry : foundEntries) { + if (idPaths.empty() || idPaths.back().id != entry.id) + idPaths.push_back({entry.id, {}}); + idPaths.back().filePathIds.push_back(entry.filePathId); + } - ProjectPartIds uniqueIds(ProjectPartIds &&ids) - { - std::sort(ids.begin(), ids.end()); - ids.erase(std::unique(ids.begin(), ids.end()), ids.end()); - - return std::move(ids); + return idPaths; } void addChangedPathForFilePath(DirectoryPathIds &&directoryPathIds) @@ -446,10 +424,12 @@ public: if (m_notifier) { WatcherEntries foundEntries = watchedEntriesForPaths(std::move(directoryPathIds)); - ProjectPartIds changedIds = idsForWatcherEntries(foundEntries); + FilePathIds watchedFilePathIds = watchedPaths(foundEntries); - m_notifier->pathsWithIdsChanged(uniqueIds(std::move(changedIds))); - m_notifier->pathsChanged(watchedPaths(foundEntries)); + std::vector changedIdPaths = idPathsForWatcherEntries(std::move(foundEntries)); + + m_notifier->pathsChanged(watchedFilePathIds); + m_notifier->pathsWithIdsChanged(changedIdPaths); } } diff --git a/src/libs/clangsupport/clangpathwatchernotifier.h b/src/libs/clangsupport/clangpathwatchernotifier.h index 393525dbf23..248925ffb92 100644 --- a/src/libs/clangsupport/clangpathwatchernotifier.h +++ b/src/libs/clangsupport/clangpathwatchernotifier.h @@ -26,9 +26,8 @@ #pragma once #include "clangsupport_global.h" - -#include -#include +#include "filepathid.h" +#include "idpaths.h" #include @@ -41,7 +40,7 @@ public: ClangPathWatcherNotifier(const ClangPathWatcherNotifier &) = delete; ClangPathWatcherNotifier &operator=(const ClangPathWatcherNotifier &) = delete; - virtual void pathsWithIdsChanged(const ProjectPartIds &ids) = 0; + virtual void pathsWithIdsChanged(const std::vector &idPaths) = 0; virtual void pathsChanged(const FilePathIds &filePathIds) = 0; protected: diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri index dc66408e581..1705be3c26d 100644 --- a/src/libs/clangsupport/clangsupport-lib.pri +++ b/src/libs/clangsupport/clangsupport-lib.pri @@ -120,6 +120,7 @@ HEADERS += \ $$PWD/projectpartid.h \ $$PWD/projectpartsstorage.h \ $$PWD/projectpartsstorageinterface.h \ + $$PWD/projectsourcechunk.h \ $$PWD/requestcompletionsmessage.h \ $$PWD/echomessage.h \ $$PWD/endmessage.h \ diff --git a/src/libs/clangsupport/idpaths.h b/src/libs/clangsupport/idpaths.h index d67a73e83e9..d0945f7ff5d 100644 --- a/src/libs/clangsupport/idpaths.h +++ b/src/libs/clangsupport/idpaths.h @@ -25,21 +25,60 @@ #pragma once -#include "projectpartid.h" #include "filepathid.h" +#include "projectpartid.h" +#include "sourceentry.h" namespace ClangBackEnd { +class ProjectChunkId +{ +public: + ProjectPartId id; + SourceType sourceType; + + friend bool operator==(ProjectChunkId first, ProjectChunkId second) + { + return first.id == second.id && first.sourceType == second.sourceType; + } + + friend bool operator==(ProjectChunkId first, ProjectPartId second) + { + return first.id == second; + } + + friend bool operator==(ProjectPartId first, ProjectChunkId second) + { + return first == second.id; + } + + friend bool operator!=(ProjectChunkId first, ProjectChunkId second) + { + return !(first == second); + } + + friend bool operator<(ProjectChunkId first, ProjectChunkId second) + { + return std::tie(first.id, first.sourceType) < std::tie(second.id, second.sourceType); + } + + friend bool operator<(ProjectChunkId first, ProjectPartId second) { return first.id < second; } + + friend bool operator<(ProjectPartId first, ProjectChunkId second) { return first < second.id; } +}; + class IdPaths { public: - ProjectPartId id; + ProjectChunkId id; FilePathIds filePathIds; - friend bool operator==(const IdPaths &first, const IdPaths &second) + friend bool operator==(IdPaths first, IdPaths second) { return first.id == second.id && first.filePathIds == second.filePathIds; } }; +using ProjectChunkIds = std::vector; + } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/precompiledheadersupdatedmessage.h b/src/libs/clangsupport/precompiledheadersupdatedmessage.h index 5bd24dcd49c..9e3e3b981c6 100644 --- a/src/libs/clangsupport/precompiledheadersupdatedmessage.h +++ b/src/libs/clangsupport/precompiledheadersupdatedmessage.h @@ -26,6 +26,7 @@ #pragma once #include "clangsupport_global.h" +#include "filepathid.h" #include "projectpartid.h" #include @@ -37,6 +38,7 @@ class PrecompiledHeadersUpdatedMessage public: PrecompiledHeadersUpdatedMessage() = default; PrecompiledHeadersUpdatedMessage(ProjectPartId projectPartId) + { projectPartIds.push_back(projectPartId); } diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp index bcf05e5d042..dd3bd3e3d60 100644 --- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp +++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp @@ -225,7 +225,8 @@ struct Data // because we have a cycle dependency PchManagerServer clangPchManagerServer{includeWatcher, pchTaskGenerator, projectParts, - generatedFiles}; + generatedFiles, + buildDependencyStorage}; TaskScheduler systemTaskScheduler{pchCreatorManager, pchTaskQueue, pchCreationProgressCounter, diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesstorage.h b/src/tools/clangpchmanagerbackend/source/builddependenciesstorage.h index 187a27cf89e..00bb429dba2 100644 --- a/src/tools/clangpchmanagerbackend/source/builddependenciesstorage.h +++ b/src/tools/clangpchmanagerbackend/source/builddependenciesstorage.h @@ -71,6 +71,11 @@ public: return fetchPchSourcesStatement.template values(1024, projectPartId.projectPathId); } + FilePathIds fetchSources(ProjectPartId projectPartId) const override + { + return fetchSourcesStatement.template values(1024, projectPartId.projectPathId); + } + void insertOrUpdateFileStatuses(const FileStatuses &fileStatuses) override { WriteStatement &statement = insertOrUpdateFileStatusesStatement; @@ -144,6 +149,94 @@ public: transaction.commit(); } + void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, + TimeStamp indexingTimeStamp) override + { + try { + Sqlite::ImmediateTransaction transaction{database}; + + for (FilePathId filePathId : filePathIds) { + inserOrUpdateIndexingTimesStampStatement.write(filePathId.filePathId, + indexingTimeStamp.value); + } + + transaction.commit(); + } catch (const Sqlite::StatementIsBusy &) { + insertOrUpdateIndexingTimeStamps(filePathIds, indexingTimeStamp); + } + } + + void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) override + { + for (FileStatus fileStatus : fileStatuses) { + inserOrUpdateIndexingTimesStampStatement.write(fileStatus.filePathId.filePathId, + fileStatus.lastModified); + } + } + + SourceTimeStamps fetchIndexingTimeStamps() const override + { + try { + Sqlite::DeferredTransaction transaction{database}; + + auto timeStamps = fetchIndexingTimeStampsStatement.template values( + 1024); + + transaction.commit(); + + return timeStamps; + } catch (const Sqlite::StatementIsBusy &) { + return fetchIndexingTimeStamps(); + } + } + + SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const override + { + try { + Sqlite::DeferredTransaction transaction{database}; + + auto timeStamps = fetchIncludedIndexingTimeStampsStatement + .template values(1024, sourcePathId.filePathId); + + transaction.commit(); + + return timeStamps; + } catch (const Sqlite::StatementIsBusy &) { + return fetchIncludedIndexingTimeStamps(sourcePathId); + } + } + + FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const override + { + try { + FilePathIds dependentSourceIds; + + Sqlite::DeferredTransaction transaction{database}; + + for (FilePathId sourcePathId : sourcePathIds) { + FilePathIds newDependentSourceIds; + newDependentSourceIds.reserve(dependentSourceIds.size() + 1024); + + auto newIds = fetchDependentSourceIdsStatement + .template values(1024, sourcePathId.filePathId); + + std::set_union(dependentSourceIds.begin(), + dependentSourceIds.end(), + newIds.begin(), + newIds.end(), + std::back_inserter(newDependentSourceIds)); + + dependentSourceIds = std::move(newDependentSourceIds); + } + + transaction.commit(); + + return dependentSourceIds; + } catch (const Sqlite::StatementIsBusy &) { + return fetchDependentSourceIds(sourcePathIds); + } + } + static Utils::SmallString toJson(const Utils::SmallStringVector &strings) { QJsonDocument document; @@ -255,6 +348,8 @@ public: "SELECT sourceId FROM projectPartsFiles WHERE projectPartId = ? AND sourceType IN (0, 1, " "3, 4) ORDER BY sourceId", database}; + mutable ReadStatement fetchSourcesStatement{ + "SELECT sourceId FROM projectPartsFiles WHERE projectPartId = ? ORDER BY sourceId", database}; mutable ReadStatement fetchSourceDependenciesStatement{ "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION " "SELECT dependencySourceId FROM sourceDependencies, " @@ -279,5 +374,24 @@ public: database}; WriteStatement deleteAllProjectPartsFilesWithProjectPartNameStatement{ "DELETE FROM projectPartsFiles WHERE projectPartId = ?", database}; + WriteStatement inserOrUpdateIndexingTimesStampStatement{ + "INSERT INTO fileStatuses(sourceId, indexingTimeStamp) VALUES (?001, ?002) ON " + "CONFLICT(sourceId) DO UPDATE SET indexingTimeStamp = ?002", + database}; + mutable ReadStatement fetchIncludedIndexingTimeStampsStatement{ + "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT " + "dependencySourceId FROM sourceDependencies, collectedDependencies WHERE " + "sourceDependencies.sourceId == collectedDependencies.sourceId) SELECT DISTINCT sourceId, " + "indexingTimeStamp FROM collectedDependencies NATURAL JOIN fileStatuses ORDER BY sourceId", + database}; + mutable ReadStatement fetchIndexingTimeStampsStatement{ + "SELECT sourceId, indexingTimeStamp FROM fileStatuses", database}; + mutable ReadStatement fetchDependentSourceIdsStatement{ + "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT " + "sourceDependencies.sourceId FROM sourceDependencies, collectedDependencies WHERE " + "sourceDependencies.dependencySourceId == collectedDependencies.sourceId) SELECT sourceId " + "FROM collectedDependencies WHERE sourceId NOT IN (SELECT dependencySourceId FROM " + "sourceDependencies) ORDER BY sourceId", + database}; }; } diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h b/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h index a1c20811aa6..953f2cca422 100644 --- a/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h +++ b/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h @@ -57,6 +57,12 @@ public: virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) = 0; virtual void updatePchCreationTimeStamp(long long pchCreationTimeStamp, ProjectPartId projectPartId) = 0; virtual FilePathIds fetchPchSources(ProjectPartId projectPartId) const = 0; + virtual FilePathIds fetchSources(ProjectPartId projectPartId) const = 0; + virtual void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) = 0; + virtual void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) = 0; + virtual SourceTimeStamps fetchIndexingTimeStamps() const = 0; + virtual SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const = 0; + virtual FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const = 0; protected: ~BuildDependenciesStorageInterface() = default; diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp index 15c9a195470..46562c39a9b 100644 --- a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp @@ -45,6 +45,8 @@ #include #include +#include + namespace ClangBackEnd { namespace { @@ -110,11 +112,28 @@ Utils::SmallStringVector PchCreator::generateClangCompilerArguments(const PchTas return builder.commandLine; } +FilePathIds PchCreator::existingSources(FilePathIds sources) const +{ + FilePathIds existingSources; + existingSources.reserve(sources.size()); + std::set_difference(sources.begin(), + sources.end(), + m_generatedFilePathIds.begin(), + m_generatedFilePathIds.end(), + std::back_inserter(existingSources)); + + return existingSources; +} + void PchCreator::generatePch(PchTask &&pchTask) { m_projectPartPch.projectPartId = pchTask.projectPartId(); m_projectPartPch.lastModified = QDateTime::currentSecsSinceEpoch(); - m_sources = std::move(pchTask.sources); + m_watchedSystemIncludes = std::move(pchTask.watchedSystemIncludes); + m_watchedProjectIncludes = std::move(pchTask.watchedProjectIncludes); + m_watchedUserIncludes = std::move(pchTask.watchedUserIncludes); + m_watchedSources = std::move(pchTask.watchedUserSources); + if (pchTask.includes.empty()) return; @@ -166,23 +185,26 @@ void PchCreator::clear() { m_clangTool = ClangTool{}; m_projectPartPch = {}; - m_sources.clear(); + m_watchedSystemIncludes.clear(); + m_watchedProjectIncludes.clear(); + m_watchedUserIncludes.clear(); + m_watchedSources.clear(); } void PchCreator::doInMainThreadAfterFinished() { if (m_projectPartPch.projectPartId.isValid()) { - FilePathIds existingSources; - existingSources.reserve(m_sources.size()); - std::set_difference(m_sources.begin(), - m_sources.end(), - m_generatedFilePathIds.begin(), - m_generatedFilePathIds.end(), - std::back_inserter(existingSources)); m_buildDependenciesStorage.updatePchCreationTimeStamp(m_projectPartPch.lastModified, m_projectPartPch.projectPartId); - m_clangPathwatcher.updateIdPaths({{m_projectPartPch.projectPartId, existingSources}}); - m_pchManagerClient.precompiledHeadersUpdated({m_projectPartPch.projectPartId}); + m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::Source}, + existingSources(m_watchedSources)}}); + m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::UserInclude}, + existingSources(m_watchedUserIncludes)}}); + m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::ProjectInclude}, + existingSources(m_watchedProjectIncludes)}}); + m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::SystemInclude}, + existingSources(m_watchedSystemIncludes)}}); + m_pchManagerClient.precompiledHeadersUpdated(m_projectPartPch.projectPartId); } } diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.h b/src/tools/clangpchmanagerbackend/source/pchcreator.h index f1fadcd33a9..c30e0110111 100644 --- a/src/tools/clangpchmanagerbackend/source/pchcreator.h +++ b/src/tools/clangpchmanagerbackend/source/pchcreator.h @@ -80,19 +80,24 @@ public: static Utils::SmallStringVector generateClangCompilerArguments(const PchTask &pchTask, FilePathView pchPath); - const ClangTool &clangTool() const - { - return m_clangTool; - } + const ClangTool &clangTool() const { return m_clangTool; } - const FilePathIds &sources() const { return m_sources; } + FilePathIds existingSources(FilePathIds sources) const; + + const FilePathIds &watchedSystemIncludes() const { return m_watchedSystemIncludes; } + const FilePathIds &watchedProjectIncludes() const { return m_watchedProjectIncludes; } + const FilePathIds &watchedUserIncludes() const { return m_watchedUserIncludes; } + const FilePathIds &watchedSources() const { return m_watchedSources; } private: mutable std::mt19937_64 randomNumberGenator{std::random_device{}()}; ClangTool m_clangTool; ProjectPartPch m_projectPartPch; FilePathCaching m_filePathCache; - FilePathIds m_sources; + FilePathIds m_watchedSystemIncludes; + FilePathIds m_watchedProjectIncludes; + FilePathIds m_watchedUserIncludes; + FilePathIds m_watchedSources; FilePathIds m_generatedFilePathIds; Environment &m_environment; PchManagerClientInterface &m_pchManagerClient; diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp index 9cce6ef4694..9fde14c7087 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp @@ -25,10 +25,11 @@ #include "pchmanagerserver.h" +#include #include +#include #include #include -#include #include #include #include @@ -39,16 +40,20 @@ #include +#include + namespace ClangBackEnd { PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher, PchTaskGeneratorInterface &pchTaskGenerator, ProjectPartsManagerInterface &projectParts, - GeneratedFilesInterface &generatedFiles) + GeneratedFilesInterface &generatedFiles, + BuildDependenciesStorageInterface &buildDependenciesStorage) : m_fileSystemWatcher(fileSystemWatcher) , m_pchTaskGenerator(pchTaskGenerator) , m_projectPartsManager(projectParts) , m_generatedFiles(generatedFiles) + , m_buildDependenciesStorage(buildDependenciesStorage) { m_fileSystemWatcher.setNotifier(this); } @@ -130,18 +135,74 @@ void PchManagerServer::removeGeneratedFiles(RemoveGeneratedFilesMessage &&messag m_generatedFiles.remove(message.takeGeneratedFiles()); } -void PchManagerServer::pathsWithIdsChanged(const ProjectPartIds &ids) +namespace { +struct FilterResults { - ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(ids); + ProjectPartIds systemIds; + ProjectPartIds projectIds; + ProjectPartIds userIds; +}; + +std::pair pchProjectPartIds(const std::vector &idPaths) +{ + ProjectPartIds changedProjectPartIds; + changedProjectPartIds.reserve(idPaths.size()); + + ProjectPartIds changedPchProjectPartIds; + changedPchProjectPartIds.reserve(idPaths.size()); + + for (const IdPaths &idPath : idPaths) { + switch (idPath.id.sourceType) { + case SourceType::TopSystemInclude: + case SourceType::SystemInclude: + case SourceType::TopProjectInclude: + case SourceType::ProjectInclude: + changedPchProjectPartIds.push_back(idPath.id.id); + break; + case SourceType::UserInclude: + case SourceType::Source: + changedProjectPartIds.push_back(idPath.id.id); + break; + } + } + + changedPchProjectPartIds.erase(std::unique(changedPchProjectPartIds.begin(), + changedPchProjectPartIds.end()), + changedPchProjectPartIds.end()); + changedPchProjectPartIds.erase(std::unique(changedPchProjectPartIds.begin(), + changedPchProjectPartIds.end()), + changedPchProjectPartIds.end()); + + ProjectPartIds changedUserProjectPartIds; + changedProjectPartIds.reserve(changedProjectPartIds.size()); + + std::set_difference(changedProjectPartIds.begin(), + changedProjectPartIds.end(), + changedPchProjectPartIds.begin(), + changedPchProjectPartIds.end(), + std::back_inserter(changedUserProjectPartIds)); + + return {changedPchProjectPartIds, changedUserProjectPartIds}; +} +} // namespace + +void PchManagerServer::pathsWithIdsChanged(const std::vector &idPaths) +{ + auto changedProjectPartIds = pchProjectPartIds(idPaths); + + ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(changedProjectPartIds.first); for (ArgumentsEntry &entry : entries) { m_pchTaskGenerator.addProjectParts(m_projectPartsManager.projects(entry.ids), std::move(entry.arguments)); } + + client()->precompiledHeadersUpdated(std::move(changedProjectPartIds.second)); } -void PchManagerServer::pathsChanged(const FilePathIds &/*filePathIds*/) +void PchManagerServer::pathsChanged(const FilePathIds &filePathIds) { + m_buildDependenciesStorage.insertOrUpdateIndexingTimeStamps(filePathIds, 0); } void PchManagerServer::setPchCreationProgress(int progress, int total) diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h index cc9daa7aa44..57b500edd91 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h @@ -39,6 +39,7 @@ namespace ClangBackEnd { class SourceRangesAndDiagnosticsForQueryMessage; class PchTaskGeneratorInterface; +class BuildDependenciesStorageInterface; class PchManagerServer : public PchManagerServerInterface, public ClangPathWatcherNotifier, @@ -49,7 +50,8 @@ public: PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher, PchTaskGeneratorInterface &pchTaskGenerator, ProjectPartsManagerInterface &projectParts, - GeneratedFilesInterface &generatedFiles); + GeneratedFilesInterface &generatedFiles, + BuildDependenciesStorageInterface &buildDependenciesStorage); void end() override; void updateProjectParts(UpdateProjectPartsMessage &&message) override; @@ -57,7 +59,7 @@ public: void updateGeneratedFiles(UpdateGeneratedFilesMessage &&message) override; void removeGeneratedFiles(RemoveGeneratedFilesMessage &&message) override; - void pathsWithIdsChanged(const ProjectPartIds &ids) override; + void pathsWithIdsChanged(const std::vector &idPaths) override; void pathsChanged(const FilePathIds &filePathIds) override; void setPchCreationProgress(int progress, int total); @@ -68,6 +70,7 @@ private: PchTaskGeneratorInterface &m_pchTaskGenerator; ProjectPartsManagerInterface &m_projectPartsManager; GeneratedFilesInterface &m_generatedFiles; + BuildDependenciesStorageInterface &m_buildDependenciesStorage; ToolChainsArgumentsCache m_toolChainsArgumentsCache; }; diff --git a/src/tools/clangpchmanagerbackend/source/pchtask.h b/src/tools/clangpchmanagerbackend/source/pchtask.h index 74b410831e4..f71a2745ad1 100644 --- a/src/tools/clangpchmanagerbackend/source/pchtask.h +++ b/src/tools/clangpchmanagerbackend/source/pchtask.h @@ -42,7 +42,10 @@ class PchTask public: PchTask(ProjectPartId projectPartId, FilePathIds &&includes, - FilePathIds &&sources, + FilePathIds &&watchedSystemIncludes, + FilePathIds &&watchedProjectIncludes, + FilePathIds &&watchedUserIncludes, + FilePathIds &&watchedUserSources, CompilerMacros &&compilerMacros, Utils::SmallStringVector &&usedMacros, // TODO remove Utils::SmallStringVector toolChainArguments, @@ -53,7 +56,10 @@ public: Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None) : projectPartIds({projectPartId}) , includes(includes) - , sources(sources) + , watchedSystemIncludes(watchedSystemIncludes) + , watchedProjectIncludes(watchedProjectIncludes) + , watchedUserIncludes(watchedUserIncludes) + , watchedUserSources(watchedUserSources) , compilerMacros(compilerMacros) , systemIncludeSearchPaths(std::move(systemIncludeSearchPaths)) , projectIncludeSearchPaths(std::move(projectIncludeSearchPaths)) @@ -65,7 +71,10 @@ public: PchTask(ProjectPartIds &&projectPartIds, FilePathIds &&includes, - FilePathIds &&sources, + FilePathIds &&watchedSystemIncludes, + FilePathIds &&watchedProjectIncludes, + FilePathIds &&watchedUserIncludes, + FilePathIds &&watchedUserSources, CompilerMacros &&compilerMacros, Utils::SmallStringVector &&usedMacros, // TODO remove Utils::SmallStringVector toolChainArguments, @@ -76,7 +85,10 @@ public: Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None) : projectPartIds(std::move(projectPartIds)) , includes(includes) - , sources(sources) + , watchedSystemIncludes(watchedSystemIncludes) + , watchedProjectIncludes(watchedProjectIncludes) + , watchedUserIncludes(watchedUserIncludes) + , watchedUserSources(watchedUserSources) , compilerMacros(compilerMacros) , systemIncludeSearchPaths(std::move(systemIncludeSearchPaths)) , projectIncludeSearchPaths(std::move(projectIncludeSearchPaths)) @@ -90,6 +102,10 @@ public: { return first.systemPchPath == second.systemPchPath && first.projectPartIds == second.projectPartIds && first.includes == second.includes + && first.watchedSystemIncludes == second.watchedSystemIncludes + && first.watchedProjectIncludes == second.watchedProjectIncludes + && first.watchedUserIncludes == second.watchedUserIncludes + && first.watchedUserSources == second.watchedUserSources && first.compilerMacros == second.compilerMacros && first.systemIncludeSearchPaths == second.systemIncludeSearchPaths && first.projectIncludeSearchPaths == second.projectIncludeSearchPaths @@ -105,7 +121,10 @@ public: FilePath systemPchPath; ProjectPartIds projectPartIds; FilePathIds includes; - FilePathIds sources; + FilePathIds watchedSystemIncludes; + FilePathIds watchedProjectIncludes; + FilePathIds watchedUserIncludes; + FilePathIds watchedUserSources; CompilerMacros compilerMacros; IncludeSearchPaths systemIncludeSearchPaths; IncludeSearchPaths projectIncludeSearchPaths; diff --git a/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp b/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp index c0a42eae395..5067d9e2656 100644 --- a/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchtaskgenerator.cpp @@ -52,6 +52,9 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts, pchTaskSets.emplace_back(PchTask{projectPart.projectPartId, std::move(filter.topSystemIncludes), {}, + {}, + {}, + {}, std::move(filter.systemCompilerMacros), std::move(filter.systemUsedMacros), projectPart.toolChainArguments, @@ -62,6 +65,9 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts, projectPart.languageExtension}, PchTask{projectPart.projectPartId, std::move(filter.topProjectIncludes), + std::move(filter.systemIncludes), + std::move(filter.projectIncludes), + std::move(filter.userIncludes), std::move(filter.sources), std::move(filter.projectCompilerMacros), std::move(filter.projectUsedMacros), diff --git a/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp b/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp index 68a8e4a6427..6436c0a0b4e 100644 --- a/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchtasksmerger.cpp @@ -98,8 +98,8 @@ bool PchTasksMerger::mergePchTasks(PchTask &firstTask, PchTask &secondTask) firstTask.projectPartIds = merge(std::move(firstTask.projectPartIds), std::move(secondTask.projectPartIds)); firstTask.includes = merge(std::move(firstTask.includes), std::move(secondTask.includes)); - firstTask.sources = merge(std::move(firstTask.sources), - std::move(secondTask.sources)); + firstTask.watchedSystemIncludes = merge(std::move(firstTask.watchedSystemIncludes), + std::move(secondTask.watchedSystemIncludes)); firstTask.compilerMacros = std::move(macros); firstTask.systemIncludeSearchPaths = mergeIncludeSearchPaths( std::move(firstTask.systemIncludeSearchPaths), diff --git a/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h b/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h index 2d16b484a1b..63bb503e75f 100644 --- a/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h +++ b/src/tools/clangpchmanagerbackend/source/usedmacrofilter.h @@ -99,6 +99,7 @@ public: projectIncludes.reserve(sources.size()); topSystemIncludes.reserve(sources.size() / 10); topProjectIncludes.reserve(sources.size() / 10); + userIncludes.reserve(sources.size()); this->sources.reserve(sources.size()); for (SourceEntry source : sources) @@ -128,23 +129,22 @@ private: case SourceType::TopSystemInclude: topSystemIncludes.emplace_back(source.sourceId); systemIncludes.emplace_back(source.sourceId); - sources.emplace_back(source.sourceId); break; case SourceType::SystemInclude: systemIncludes.emplace_back(source.sourceId); - sources.emplace_back(source.sourceId); break; case SourceType::TopProjectInclude: topProjectIncludes.emplace_back(source.sourceId); projectIncludes.emplace_back(source.sourceId); - sources.emplace_back(source.sourceId); break; case SourceType::ProjectInclude: projectIncludes.emplace_back(source.sourceId); - sources.emplace_back(source.sourceId); break; case SourceType::UserInclude: + userIncludes.emplace_back(source.sourceId); + break; case SourceType::Source: + sources.emplace_back(source.sourceId); break; } @@ -215,6 +215,7 @@ private: public: FilePathIds sources; + FilePathIds userIncludes; FilePathIds projectIncludes; FilePathIds systemIncludes; FilePathIds topProjectIncludes; diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp index 4f3a6f172f3..4d042b3fd33 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp @@ -98,7 +98,7 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart) std::vector symbolIndexerTask; symbolIndexerTask.reserve(projectPart.sourcePathIds.size()); for (FilePathId sourcePathId : projectPart.sourcePathIds) { - SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps( + SourceTimeStamps dependentTimeStamps = m_buildDependencyStorage.fetchIncludedIndexingTimeStamps( sourcePathId); if (!m_modifiedTimeChecker.isUpToDate(dependentTimeStamps)) { @@ -122,7 +122,8 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart) auto store = [&] { Sqlite::ImmediateTransaction transaction{m_transactionInterface}; - m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses()); + m_buildDependencyStorage.insertOrUpdateIndexingTimeStamps( + symbolsCollector.fileStatuses()); m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), symbolsCollector.sourceLocations()); transaction.commit(); @@ -144,28 +145,17 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart) } } - m_pathWatcher.updateIdPaths( - {{projectPartId, m_buildDependencyStorage.fetchPchSources(projectPartId)}}); + m_pathWatcher.updateIdPaths({{{projectPartId, SourceType::Source}, + m_buildDependencyStorage.fetchPchSources(projectPartId)}}); m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask)); m_symbolIndexerTaskQueue.processEntries(); } -void SymbolIndexer::pathsWithIdsChanged(const ProjectPartIds &) {} +void SymbolIndexer::pathsWithIdsChanged(const std::vector &) {} void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds) { m_modifiedTimeChecker.pathsChanged(filePathIds); - - FilePathIds dependentSourcePathIds = m_symbolStorage.fetchDependentSourceIds(filePathIds); - - std::vector symbolIndexerTask; - symbolIndexerTask.reserve(dependentSourcePathIds.size()); - - for (FilePathId dependentSourcePathId : dependentSourcePathIds) - updateChangedPath(dependentSourcePathId, symbolIndexerTask); - - m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask)); - m_symbolIndexerTaskQueue.processEntries(); } void SymbolIndexer::updateChangedPath(FilePathId filePathId, @@ -182,7 +172,8 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId, ProjectPartId projectPartId = optionalArtefact->projectPartId; - SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(filePathId); + SourceTimeStamps dependentTimeStamps = m_buildDependencyStorage.fetchIncludedIndexingTimeStamps( + filePathId); auto indexing = [optionalArtefact = std::move(optionalArtefact), filePathId, @@ -207,7 +198,7 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId, auto store = [&] { Sqlite::ImmediateTransaction transaction{m_transactionInterface}; - m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses()); + m_buildDependencyStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses()); m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), symbolsCollector.sourceLocations()); transaction.commit(); diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.h b/src/tools/clangrefactoringbackend/source/symbolindexer.h index d969cd80264..67da0c9774d 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexer.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexer.h @@ -60,7 +60,7 @@ public: void updateProjectParts(ProjectPartContainers &&projectParts); void updateProjectPart(ProjectPartContainer &&projectPart); - void pathsWithIdsChanged(const ProjectPartIds &ids) override; + void pathsWithIdsChanged(const std::vector &idPaths) override; void pathsChanged(const FilePathIds &filePathIds) override; void updateChangedPath(FilePathId filePath, std::vector &symbolIndexerTask); @@ -75,6 +75,9 @@ public: FilePathIds updatableFilePathIds(const ProjectPartContainer &projectPart, const Utils::optional &optionalArtefact) const; +private: + FilePathIds filterProjectPartSources(const FilePathIds &filePathIds) const; + private: SymbolIndexerTaskQueueInterface &m_symbolIndexerTaskQueue; SymbolStorageInterface &m_symbolStorage; diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.h b/src/tools/clangrefactoringbackend/source/symbolstorage.h index 3d7d4c9784d..cf7d64e8003 100644 --- a/src/tools/clangrefactoringbackend/source/symbolstorage.h +++ b/src/tools/clangrefactoringbackend/source/symbolstorage.h @@ -70,93 +70,6 @@ public: deleteNewLocationsTable(); } - void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) override - { - try { - Sqlite::ImmediateTransaction transaction{database}; - - for (FilePathId filePathId : filePathIds) { - inserOrUpdateIndexingTimesStampStatement.write(filePathId.filePathId, - indexingTimeStamp.value); - } - - transaction.commit(); - } catch (const Sqlite::StatementIsBusy &) { - insertOrUpdateIndexingTimeStamps(filePathIds, indexingTimeStamp); - } - } - - void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) override - { - for (FileStatus fileStatus : fileStatuses) { - inserOrUpdateIndexingTimesStampStatement.write(fileStatus.filePathId.filePathId, - fileStatus.lastModified); - } - } - - SourceTimeStamps fetchIndexingTimeStamps() const override - { - try { - Sqlite::DeferredTransaction transaction{database}; - - auto timeStamps = fetchIndexingTimeStampsStatement.template values( - 1024); - - transaction.commit(); - - return timeStamps; - } catch (const Sqlite::StatementIsBusy &) { - return fetchIndexingTimeStamps(); - } - } - - SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const override - { - try { - Sqlite::DeferredTransaction transaction{database}; - - auto timeStamps = fetchIncludedIndexingTimeStampsStatement - .template values(1024, sourcePathId.filePathId); - - transaction.commit(); - - return timeStamps; - } catch (const Sqlite::StatementIsBusy &) { - return fetchIncludedIndexingTimeStamps(sourcePathId); - } - } - - FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const override - { - try { - FilePathIds dependentSourceIds; - - Sqlite::DeferredTransaction transaction{database}; - - for (FilePathId sourcePathId : sourcePathIds) { - FilePathIds newDependentSourceIds; - newDependentSourceIds.reserve(dependentSourceIds.size() + 1024); - - auto newIds = fetchDependentSourceIdsStatement - .template values(1024, sourcePathId.filePathId); - - std::set_union(dependentSourceIds.begin(), - dependentSourceIds.end(), - newIds.begin(), - newIds.end(), - std::back_inserter(newDependentSourceIds)); - - dependentSourceIds = std::move(newDependentSourceIds); - } - - transaction.commit(); - - return dependentSourceIds; - } catch (const Sqlite::StatementIsBusy &) { - return fetchDependentSourceIds(sourcePathIds); - } - } - void fillTemporarySymbolsTable(const SymbolEntries &symbolEntries) { WriteStatement &statement = insertSymbolsToNewSymbolsStatement; @@ -278,25 +191,6 @@ public: database}; WriteStatement deleteNewSymbolsTableStatement{"DELETE FROM newSymbols", database}; WriteStatement deleteNewLocationsTableStatement{"DELETE FROM newLocations", database}; - WriteStatement inserOrUpdateIndexingTimesStampStatement{ - "INSERT INTO fileStatuses(sourceId, indexingTimeStamp) VALUES (?001, ?002) ON " - "CONFLICT(sourceId) DO UPDATE SET indexingTimeStamp = ?002", - database}; - mutable ReadStatement fetchIncludedIndexingTimeStampsStatement{ - "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT " - "dependencySourceId FROM sourceDependencies, collectedDependencies WHERE " - "sourceDependencies.sourceId == collectedDependencies.sourceId) SELECT DISTINCT sourceId, " - "indexingTimeStamp FROM collectedDependencies NATURAL JOIN fileStatuses ORDER BY sourceId", - database}; - mutable ReadStatement fetchIndexingTimeStampsStatement{ - "SELECT sourceId, indexingTimeStamp FROM fileStatuses", database}; - mutable ReadStatement fetchDependentSourceIdsStatement{ - "WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT " - "sourceDependencies.sourceId FROM sourceDependencies, collectedDependencies WHERE " - "sourceDependencies.dependencySourceId == collectedDependencies.sourceId) SELECT sourceId " - "FROM collectedDependencies WHERE sourceId NOT IN (SELECT dependencySourceId FROM " - "sourceDependencies) ORDER BY sourceId", - database}; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h index d3c8035e8c6..1d0328e9f82 100644 --- a/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h +++ b/src/tools/clangrefactoringbackend/source/symbolstorageinterface.h @@ -48,11 +48,6 @@ public: virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries, const SourceLocationEntries &sourceLocations) = 0; - virtual void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) = 0; - virtual void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) = 0; - virtual SourceTimeStamps fetchIndexingTimeStamps() const = 0; - virtual SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const = 0; - virtual FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const = 0; protected: ~SymbolStorageInterface() = default; diff --git a/tests/unit/unittest/builddependenciesstorage-test.cpp b/tests/unit/unittest/builddependenciesstorage-test.cpp index d14b94fe30d..56f8b42ac5b 100644 --- a/tests/unit/unittest/builddependenciesstorage-test.cpp +++ b/tests/unit/unittest/builddependenciesstorage-test.cpp @@ -28,8 +28,11 @@ #include "mockfilepathcaching.h" #include "mocksqlitedatabase.h" -#include #include +#include +#include +#include +#include #include @@ -70,7 +73,12 @@ protected: MockSqliteWriteStatement &updatePchCreationTimeStampStatement = storage.updatePchCreationTimeStampStatement; MockSqliteWriteStatement &deleteAllProjectPartsFilesWithProjectPartNameStatement = storage.deleteAllProjectPartsFilesWithProjectPartNameStatement; - MockSqliteReadStatement &fetchProjectPartsFilesStatement = storage.fetchPchSourcesStatement; + MockSqliteReadStatement &fetchPchSourcesStatement = storage.fetchPchSourcesStatement; + MockSqliteReadStatement &fetchSourcesStatement = storage.fetchSourcesStatement; + MockSqliteWriteStatement &inserOrUpdateIndexingTimesStampStatement = storage.inserOrUpdateIndexingTimesStampStatement; + MockSqliteReadStatement &fetchIndexingTimeStampsStatement = storage.fetchIndexingTimeStampsStatement; + MockSqliteReadStatement &fetchIncludedIndexingTimeStampsStatement = storage.fetchIncludedIndexingTimeStampsStatement; + MockSqliteReadStatement &fetchDependentSourceIdsStatement = storage.fetchDependentSourceIdsStatement; }; TEST_F(BuildDependenciesStorage, ConvertStringsToJson) @@ -233,13 +241,163 @@ TEST_F(BuildDependenciesStorage, FetchUsedMacros) ASSERT_THAT(usedMacros, result); } -TEST_F(BuildDependenciesStorage, FetchSources) +TEST_F(BuildDependenciesStorage, FetchPchSources) { ClangBackEnd::FilePathIds result{3, 5, 7}; - EXPECT_CALL(fetchProjectPartsFilesStatement, valuesReturnFilePathIds(_, 22)).WillOnce(Return(result)); + EXPECT_CALL(fetchPchSourcesStatement, valuesReturnFilePathIds(_, 22)).WillOnce(Return(result)); auto sources = storage.fetchPchSources(22); ASSERT_THAT(sources, result); } + +TEST_F(BuildDependenciesStorage, FetchSources) +{ + ClangBackEnd::FilePathIds result{3, 5, 7}; + EXPECT_CALL(fetchSourcesStatement, valuesReturnFilePathIds(_, 22)).WillOnce(Return(result)); + + auto sources = storage.fetchSources(22); + + ASSERT_THAT(sources, result); +} + +TEST_F(BuildDependenciesStorage, FetchIndexingTimeStampsIsBusy) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024)) + .WillOnce(Throw(Sqlite::StatementIsBusy{""})); + EXPECT_CALL(mockDatabase, rollback()); + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024)); + EXPECT_CALL(mockDatabase, commit()); + + storage.fetchIndexingTimeStamps(); +} + +TEST_F(BuildDependenciesStorage, InsertIndexingTimeStamp) +{ + ClangBackEnd::FileStatuses fileStatuses{{1, 0, 34}, {2, 0, 37}}; + + EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq(1), TypedEq(34))); + EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq(2), TypedEq(37))); + + storage.insertOrUpdateIndexingTimeStamps(fileStatuses); +} + +TEST_F(BuildDependenciesStorage, InsertIndexingTimeStampsIsBusy) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""})); + EXPECT_CALL(mockDatabase, immediateBegin()); + EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq(1), TypedEq(34))); + EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq(2), TypedEq(34))); + EXPECT_CALL(mockDatabase, commit()); + + storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34); +} + +TEST_F(BuildDependenciesStorage, FetchIncludedIndexingTimeStampsIsBusy) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement, + valuesReturnSourceTimeStamps(1024, TypedEq(1))) + .WillOnce(Throw(Sqlite::StatementIsBusy{""})); + EXPECT_CALL(mockDatabase, rollback()); + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement, + valuesReturnSourceTimeStamps(1024, TypedEq(1))); + EXPECT_CALL(mockDatabase, commit()); + + storage.fetchIncludedIndexingTimeStamps(1); +} + +TEST_F(BuildDependenciesStorage, FetchDependentSourceIdsIsBusy) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq(3))); + EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq(2))) + .WillOnce(Throw(Sqlite::StatementIsBusy{""})); + EXPECT_CALL(mockDatabase, rollback()); + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq(3))); + EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq(2))); + EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq(7))); + EXPECT_CALL(mockDatabase, commit()); + + storage.fetchDependentSourceIds({3, 2, 7}); +} + +class BuildDependenciesStorageSlow : public testing::Test +{ +protected: + Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; + ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; + ClangBackEnd::BuildDependenciesStorage<> storage{database}; +}; + +TEST_F(BuildDependenciesStorageSlow, InsertIndexingTimeStamps) +{ + storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34); + + ASSERT_THAT(storage.fetchIndexingTimeStamps(), + ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 34})); +} + +TEST_F(BuildDependenciesStorageSlow, UpdateIndexingTimeStamps) +{ + storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34); + + storage.insertOrUpdateIndexingTimeStamps({1}, 37); + + ASSERT_THAT(storage.fetchIndexingTimeStamps(), + ElementsAre(SourceTimeStamp{1, 37}, SourceTimeStamp{2, 34})); +} + +TEST_F(BuildDependenciesStorageSlow, InsertIndexingTimeStamp) +{ + storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 37}}); + + ASSERT_THAT(storage.fetchIndexingTimeStamps(), + ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37})); +} + +TEST_F(BuildDependenciesStorageSlow, UpdateIndexingTimeStamp) +{ + storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 34}}); + + storage.insertOrUpdateIndexingTimeStamps({{2, 0, 37}}); + + ASSERT_THAT(storage.fetchIndexingTimeStamps(), + ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37})); +} + +TEST_F(BuildDependenciesStorageSlow, FetchIncludedIndexingTimeStamps) +{ + storage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5}, 34); + storage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {3, 4}, {5, 3}}); + + auto timeStamps = storage.fetchIncludedIndexingTimeStamps(1); + + ASSERT_THAT(timeStamps, + ElementsAre(SourceTimeStamp{1, 34}, + SourceTimeStamp{2, 34}, + SourceTimeStamp{3, 34}, + SourceTimeStamp{4, 34})); +} + +TEST_F(BuildDependenciesStorageSlow, FetchDependentSourceIds) +{ + storage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {4, 2}, {5, 6}, {7, 6}}); + + auto sourceIds = storage.fetchDependentSourceIds({3, 2, 7}); + + ASSERT_THAT(sourceIds, ElementsAre(FilePathId{1}, FilePathId{4}, FilePathId{7})); +} } // namespace diff --git a/tests/unit/unittest/clangpathwatcher-test.cpp b/tests/unit/unittest/clangpathwatcher-test.cpp index f4d99e358d7..3105000ca18 100644 --- a/tests/unit/unittest/clangpathwatcher-test.cpp +++ b/tests/unit/unittest/clangpathwatcher-test.cpp @@ -48,8 +48,11 @@ using ClangBackEnd::FilePath; using ClangBackEnd::FilePathId; using ClangBackEnd::FilePathIds; using ClangBackEnd::FilePathView; +using ClangBackEnd::IdPaths; +using ClangBackEnd::ProjectChunkId; using ClangBackEnd::ProjectPartId; using ClangBackEnd::ProjectPartIds; +using ClangBackEnd::SourceType; using ClangBackEnd::WatcherEntries; using ClangBackEnd::WatcherEntry; @@ -111,9 +114,9 @@ protected: NiceMock mockFileSystem; Watcher watcher{mockFilePathCache, mockFileSystem, ¬ifier}; NiceMock &mockQFileSytemWatcher = watcher.fileSystemWatcher(); - ProjectPartId id1{2}; - ProjectPartId id2{3}; - ProjectPartId id3{4}; + ProjectChunkId id1{2, SourceType::ProjectInclude}; + ProjectChunkId id2{2, SourceType::Source}; + ProjectChunkId id3{4, SourceType::SystemInclude}; FilePathView path1{"/path/path1"}; FilePathView path2{"/path/path2"}; FilePathView path3{"/path2/path1"}; @@ -128,14 +131,15 @@ protected: Utils::PathString directoryPathString2 = directoryPath2; FilePathIds pathIds = {1, 2, 3, 4, 5}; ClangBackEnd::DirectoryPathIds directoryPaths = {1, 2, 3}; - ClangBackEnd::ProjectPartIds ids{id1, id2, id3}; - WatcherEntry watcherEntry1{ids[0], directoryPaths[0], pathIds[0]}; - WatcherEntry watcherEntry2{ids[1], directoryPaths[0], pathIds[0]}; - WatcherEntry watcherEntry3{ids[0], directoryPaths[0], pathIds[1]}; - WatcherEntry watcherEntry4{ids[1], directoryPaths[0], pathIds[1]}; - WatcherEntry watcherEntry5{ids[2], directoryPaths[0], pathIds[1]}; - WatcherEntry watcherEntry6{ids[0], directoryPaths[1], pathIds[2]}; - WatcherEntry watcherEntry7{ids[1], directoryPaths[1], pathIds[3]}; + ClangBackEnd::ProjectChunkIds ids{id1, id2, id3}; + WatcherEntry watcherEntry1{id1, directoryPaths[0], pathIds[0]}; + WatcherEntry watcherEntry2{id2, directoryPaths[0], pathIds[0]}; + WatcherEntry watcherEntry3{id1, directoryPaths[0], pathIds[1]}; + WatcherEntry watcherEntry4{id2, directoryPaths[0], pathIds[1]}; + WatcherEntry watcherEntry5{id3, directoryPaths[0], pathIds[1]}; + WatcherEntry watcherEntry6{id1, directoryPaths[1], pathIds[2]}; + WatcherEntry watcherEntry7{id2, directoryPaths[1], pathIds[3]}; + WatcherEntry watcherEntry8{id3, directoryPaths[1], pathIds[3]}; }; TEST_F(ClangPathWatcher, AddIdPaths) @@ -260,12 +264,13 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths) TEST_F(ClangPathWatcher, RemoveEntriesWithId) { - watcher.updateIdPaths( - {{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[1]}}}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, + {id2, {pathIds[0], pathIds[1]}}, + {id3, {pathIds[1], pathIds[3]}}}); - watcher.removeIds({id1}); + watcher.removeIds({2}); - ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry2, watcherEntry4, watcherEntry5)); + ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry5, watcherEntry8)); } TEST_F(ClangPathWatcher, RemoveNoPathsForEmptyIds) @@ -284,28 +289,28 @@ TEST_F(ClangPathWatcher, RemoveNoPathsForOneId) EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)) .Times(0); - watcher.removeIds({id3}); + watcher.removeIds({id3.id}); } TEST_F(ClangPathWatcher, RemovePathForOneId) { watcher.updateIdPaths( - {{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); + {{id1, {pathIds[0], pathIds[1]}}, {id3, {pathIds[0], pathIds[1], pathIds[3]}}}); EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath2))); - watcher.removeIds({id2}); + watcher.removeIds({id3.id}); } TEST_F(ClangPathWatcher, RemoveNoPathSecondTime) { watcher.updateIdPaths( {{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); - watcher.removeIds({id2}); + watcher.removeIds({id2.id}); EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)).Times(0); - watcher.removeIds({id2}); + watcher.removeIds({id2.id}); } TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId) @@ -315,7 +320,7 @@ TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId) EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath, directoryPath2))); - watcher.removeIds({id1, id2, id3}); + watcher.removeIds({id1.id, id2.id, id3.id}); } TEST_F(ClangPathWatcher, RemoveOnePathForTwoId) @@ -325,7 +330,7 @@ TEST_F(ClangPathWatcher, RemoveOnePathForTwoId) EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath))); - watcher.removeIds({id1, id2}); + watcher.removeIds({id1.id, id2.id}); } TEST_F(ClangPathWatcher, NotAnymoreWatchedEntriesWithId) @@ -349,13 +354,14 @@ TEST_F(ClangPathWatcher, RemoveUnusedEntries) TEST_F(ClangPathWatcher, TwoNotifyFileChanges) { watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2]}}, - {id2, {pathIds[0], pathIds[1], pathIds[3]}}, + {id2, {pathIds[0], pathIds[1], pathIds[2], pathIds[3], pathIds[4]}}, {id3, {pathIds[4]}}}); ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2)); ON_CALL(mockFileSystem, lastModified(Eq(pathIds[1]))).WillByDefault(Return(2)); ON_CALL(mockFileSystem, lastModified(Eq(pathIds[3]))).WillByDefault(Return(2)); - EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id1, id2))); + EXPECT_CALL(notifier, + pathsWithIdsChanged(ElementsAre(IdPaths{id1, {1, 2}}, IdPaths{id2, {1, 2, 4}}))); mockQFileSytemWatcher.directoryChanged(directoryPath); mockQFileSytemWatcher.directoryChanged(directoryPath2); diff --git a/tests/unit/unittest/commandlinebuilder-test.cpp b/tests/unit/unittest/commandlinebuilder-test.cpp index c5765037dc5..08c4e32f766 100644 --- a/tests/unit/unittest/commandlinebuilder-test.cpp +++ b/tests/unit/unittest/commandlinebuilder-test.cpp @@ -52,8 +52,8 @@ public: CommandLineBuilder() { cppProjectInfo.language = Utils::Language::Cxx; } public: - ClangBackEnd::PchTask emptyProjectInfo{0, {}, {}, {}, {}, {}, {}, {}}; - ClangBackEnd::PchTask cppProjectInfo{1, {}, {}, {}, {}, {}, {}, {}}; + ClangBackEnd::PchTask emptyProjectInfo{0, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}}; + ClangBackEnd::PchTask cppProjectInfo{1, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}}; }; template <> diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 0ab962dfa55..e1f721440f5 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -359,9 +359,8 @@ std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry) std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry) { - out << "(" - << entry.id << ", " - << entry.filePathId + out << "(" << entry.directoryPathId << ", " << entry.filePathId << ", " << entry.id << ", " + << entry.lastModified << ", " << ")"; return out; @@ -1290,6 +1289,17 @@ std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths) { return out << "(" << pchPaths.projectPchPath << ", " << pchPaths.systemPchPath << ")"; } + +std::ostream &operator<<(std::ostream &out, const ProjectChunkId &chunk) +{ + return out << "(" << chunk.id << ", " << typeToString(chunk.sourceType) << ")"; +} + +std::ostream &operator<<(std::ostream &out, const DirectoryPathId &id) +{ + return out << id.directoryPathId; +} + void PrintTo(const FilePath &filePath, ::std::ostream *os) { *os << filePath; diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index b874fc90e4b..057ebba139b 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -200,6 +200,8 @@ struct ArgumentsEntry; class ProjectPartContainer; class ProjectPartId; class PchPaths; +class ProjectChunkId; +class DirectoryPathId; std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry); std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths); @@ -293,6 +295,8 @@ 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); std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths); +std::ostream &operator<<(std::ostream &out, const ProjectChunkId &chunk); +std::ostream &operator<<(std::ostream &out, const DirectoryPathId &id); void PrintTo(const FilePath &filePath, ::std::ostream *os); void PrintTo(const FilePathView &filePathView, ::std::ostream *os); diff --git a/tests/unit/unittest/mockbuilddependenciesstorage.h b/tests/unit/unittest/mockbuilddependenciesstorage.h index dd2850d88cc..0436e27f92b 100644 --- a/tests/unit/unittest/mockbuilddependenciesstorage.h +++ b/tests/unit/unittest/mockbuilddependenciesstorage.h @@ -53,5 +53,16 @@ public: void(long long pchCreationTimeStamp, ClangBackEnd::ProjectPartId projectPartId)); MOCK_CONST_METHOD1(fetchPchSources, ClangBackEnd::FilePathIds(ClangBackEnd::ProjectPartId projectPartId)); + MOCK_CONST_METHOD1(fetchSources, + ClangBackEnd::FilePathIds(ClangBackEnd::ProjectPartId projectPartId)); + MOCK_METHOD2(insertOrUpdateIndexingTimeStamps, + void(const ClangBackEnd::FilePathIds &filePathIds, + ClangBackEnd::TimeStamp indexingTimeStamp)); + MOCK_METHOD1(insertOrUpdateIndexingTimeStamps, void(const ClangBackEnd::FileStatuses &)); + MOCK_CONST_METHOD0(fetchIndexingTimeStamps, ClangBackEnd::SourceTimeStamps()); + MOCK_CONST_METHOD1(fetchIncludedIndexingTimeStamps, + ClangBackEnd::SourceTimeStamps(ClangBackEnd::FilePathId sourcePathId)); + MOCK_CONST_METHOD1(fetchDependentSourceIds, + ClangBackEnd::FilePathIds(const ClangBackEnd::FilePathIds &sourcePathIds)); }; diff --git a/tests/unit/unittest/mockclangpathwatchernotifier.h b/tests/unit/unittest/mockclangpathwatchernotifier.h index c89f37adafe..8d8b8b1369a 100644 --- a/tests/unit/unittest/mockclangpathwatchernotifier.h +++ b/tests/unit/unittest/mockclangpathwatchernotifier.h @@ -32,7 +32,7 @@ class MockClangPathWatcherNotifier : public ClangBackEnd::ClangPathWatcherNotifier { public: - MOCK_METHOD1(pathsWithIdsChanged, void(const ClangBackEnd::ProjectPartIds &ids)); + MOCK_METHOD1(pathsWithIdsChanged, void(const std::vector &idPaths)); MOCK_METHOD1(pathsChanged, void (const ClangBackEnd::FilePathIds &filePathIds)); diff --git a/tests/unit/unittest/mocksymbolstorage.h b/tests/unit/unittest/mocksymbolstorage.h index 7b77868e8a8..a1743897358 100644 --- a/tests/unit/unittest/mocksymbolstorage.h +++ b/tests/unit/unittest/mocksymbolstorage.h @@ -37,11 +37,4 @@ public: MOCK_METHOD2(addSymbolsAndSourceLocations, void(const ClangBackEnd::SymbolEntries &symbolEentries, const ClangBackEnd::SourceLocationEntries &sourceLocations)); - MOCK_METHOD2(insertOrUpdateIndexingTimeStamps, - void(const FilePathIds &filePathIds, ClangBackEnd::TimeStamp indexingTimeStamp)); - MOCK_METHOD1(insertOrUpdateIndexingTimeStamps, void(const ClangBackEnd::FileStatuses &)); - MOCK_CONST_METHOD0(fetchIndexingTimeStamps, ClangBackEnd::SourceTimeStamps()); - MOCK_CONST_METHOD1(fetchIncludedIndexingTimeStamps, - ClangBackEnd::SourceTimeStamps(ClangBackEnd::FilePathId sourcePathId)); - MOCK_CONST_METHOD1(fetchDependentSourceIds, FilePathIds(const FilePathIds &sourcePathIds)); }; diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp index 04e198eec75..e6ae4a943d0 100644 --- a/tests/unit/unittest/pchcreator-test.cpp +++ b/tests/unit/unittest/pchcreator-test.cpp @@ -34,12 +34,13 @@ #include "mockpchmanagerclient.h" #include "testenvironment.h" -#include #include #include #include #include #include +#include +#include #include @@ -55,12 +56,14 @@ using ClangBackEnd::GeneratedFiles; using ClangBackEnd::IdPaths; using ClangBackEnd::IncludeSearchPathType; using ClangBackEnd::PchTask; +using ClangBackEnd::PrecompiledHeadersUpdatedMessage; +using ClangBackEnd::ProjectChunkId; +using ClangBackEnd::ProjectPartContainer; using ClangBackEnd::ProjectPartPch; using ClangBackEnd::SourceEntries; using ClangBackEnd::SourceEntry; using ClangBackEnd::SourceType; using ClangBackEnd::V2::FileContainer; -using ClangBackEnd::ProjectPartContainer; using Utils::PathString; using Utils::SmallString; @@ -91,6 +94,13 @@ protected: return creator.filePathCache().filePathId(path); } + FilePathIds sorted(FilePathIds &&filePathIds) + { + std::sort(filePathIds.begin(), filePathIds.end()); + + return std::move(filePathIds); + } + protected: Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; @@ -111,14 +121,19 @@ protected: mockBuildDependenciesStorage}; PchTask pchTask1{ 1, - {id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), - id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), - id(TESTDATA_DIR "/builddependencycollector/external/external2.h")}, - {id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), - id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), - id(TESTDATA_DIR "/builddependencycollector/external/external2.h"), - id(generatedFilePath), - id(main2Path)}, + sorted({id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), + id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), + id(TESTDATA_DIR "/builddependencycollector/external/external2.h")}), + sorted({id(TESTDATA_DIR "/builddependencycollector/system/system1.h"), + id(TESTDATA_DIR "/builddependencycollector/system/system2.h"), + id(generatedFilePath)}), + sorted({id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), + id(TESTDATA_DIR "/builddependencycollector/external/external2.h"), + id(generatedFilePath)}), + sorted({id(TESTDATA_DIR "/builddependencycollector/project/header1.h"), + id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), + id(generatedFilePath)}), + sorted({id(main2Path), id(generatedFilePath)}), {}, {}, {}, @@ -213,15 +228,34 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterSucess) { creator.generatePch(std::move(pchTask1)); + EXPECT_CALL(mockClangPathWatcher, + updateIdPaths(ElementsAre( + AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}), + Field(&ClangBackEnd::IdPaths::filePathIds, + UnorderedElementsAre(id(main2Path))))))); + EXPECT_CALL(mockClangPathWatcher, updateIdPaths(ElementsAre(AllOf( - Field(&ClangBackEnd::IdPaths::id, 1), + Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}), Field(&ClangBackEnd::IdPaths::filePathIds, UnorderedElementsAre( - id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), - id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), - id(TESTDATA_DIR "/builddependencycollector/external/external2.h"), - id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp"))))))); + id(TESTDATA_DIR "/builddependencycollector/project/header1.h"), + id(TESTDATA_DIR "/builddependencycollector/project/header2.h"))))))); + EXPECT_CALL( + mockClangPathWatcher, + updateIdPaths(ElementsAre( + AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}), + Field(&ClangBackEnd::IdPaths::filePathIds, + UnorderedElementsAre( + id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), + id(TESTDATA_DIR "/builddependencycollector/external/external2.h"))))))); + EXPECT_CALL(mockClangPathWatcher, + updateIdPaths(ElementsAre(AllOf( + Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}), + Field(&ClangBackEnd::IdPaths::filePathIds, + UnorderedElementsAre( + id(TESTDATA_DIR "/builddependencycollector/system/system1.h"), + id(TESTDATA_DIR "/builddependencycollector/system/system2.h"))))))); creator.doInMainThreadAfterFinished(); } @@ -232,15 +266,34 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterFail) pchTask1.projectIncludeSearchPaths = {}; creator.generatePch(std::move(pchTask1)); + EXPECT_CALL(mockClangPathWatcher, + updateIdPaths(ElementsAre( + AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}), + Field(&ClangBackEnd::IdPaths::filePathIds, + UnorderedElementsAre(id(main2Path))))))); + EXPECT_CALL(mockClangPathWatcher, updateIdPaths(ElementsAre(AllOf( - Field(&ClangBackEnd::IdPaths::id, 1), + Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}), Field(&ClangBackEnd::IdPaths::filePathIds, UnorderedElementsAre( - id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), - id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), - id(TESTDATA_DIR "/builddependencycollector/external/external2.h"), - id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp"))))))); + id(TESTDATA_DIR "/builddependencycollector/project/header1.h"), + id(TESTDATA_DIR "/builddependencycollector/project/header2.h"))))))); + EXPECT_CALL( + mockClangPathWatcher, + updateIdPaths(ElementsAre( + AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}), + Field(&ClangBackEnd::IdPaths::filePathIds, + UnorderedElementsAre( + id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), + id(TESTDATA_DIR "/builddependencycollector/external/external2.h"))))))); + EXPECT_CALL(mockClangPathWatcher, + updateIdPaths(ElementsAre(AllOf( + Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}), + Field(&ClangBackEnd::IdPaths::filePathIds, + UnorderedElementsAre( + id(TESTDATA_DIR "/builddependencycollector/system/system1.h"), + id(TESTDATA_DIR "/builddependencycollector/system/system2.h"))))))); creator.doInMainThreadAfterFinished(); } @@ -282,15 +335,40 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchCleared) ASSERT_FALSE(creator.projectPartPch().isValid()); } -TEST_F(PchCreatorVerySlowTest, SourcesCleared) +TEST_F(PchCreatorVerySlowTest, WatchedSystemIncludesCleared) { creator.generatePch(std::move(pchTask1)); creator.clear(); - ASSERT_THAT(creator.sources(), IsEmpty()); + ASSERT_THAT(creator.watchedSystemIncludes(), IsEmpty()); } +TEST_F(PchCreatorVerySlowTest, WatchedProjectIncludesCleared) +{ + creator.generatePch(std::move(pchTask1)); + + creator.clear(); + + ASSERT_THAT(creator.watchedProjectIncludes(), IsEmpty()); +} + +TEST_F(PchCreatorVerySlowTest, WatchedUserIncludesCleared) +{ + creator.generatePch(std::move(pchTask1)); + + creator.clear(); + + ASSERT_THAT(creator.watchedUserIncludes(), IsEmpty()); +} +TEST_F(PchCreatorVerySlowTest, WatchedSourcesCleared) +{ + creator.generatePch(std::move(pchTask1)); + + creator.clear(); + + ASSERT_THAT(creator.watchedSources(), IsEmpty()); +} TEST_F(PchCreatorVerySlowTest, ClangToolCleared) { creator.generatePch(std::move(pchTask1)); @@ -306,6 +384,9 @@ TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesFaultyPchForPchTask 0, {id(TESTDATA_DIR "/builddependencycollector/project/faulty.cpp")}, {}, + {}, + {}, + {}, {{"DEFINE", "1", 1}}, {}, {}, @@ -336,20 +417,37 @@ TEST_F(PchCreatorSlowTest, NoIncludesInTheMainThreadCalls) { pchTask1.includes = {}; creator.generatePch(std::move(pchTask1)); - EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated( Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds, ElementsAre(Eq(creator.projectPartPch().projectPartId))))); + EXPECT_CALL(mockClangPathWatcher, + updateIdPaths(ElementsAre( + AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}), + Field(&ClangBackEnd::IdPaths::filePathIds, + UnorderedElementsAre(id(main2Path))))))); EXPECT_CALL(mockClangPathWatcher, updateIdPaths(ElementsAre(AllOf( - Field(&ClangBackEnd::IdPaths::id, 1), + Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}), Field(&ClangBackEnd::IdPaths::filePathIds, UnorderedElementsAre( - id(TESTDATA_DIR "/builddependencycollector/project/header2.h"), - id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), - id(TESTDATA_DIR "/builddependencycollector/external/external2.h"), - id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp"))))))); + id(TESTDATA_DIR "/builddependencycollector/project/header1.h"), + id(TESTDATA_DIR "/builddependencycollector/project/header2.h"))))))); + EXPECT_CALL( + mockClangPathWatcher, + updateIdPaths(ElementsAre( + AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}), + Field(&ClangBackEnd::IdPaths::filePathIds, + UnorderedElementsAre( + id(TESTDATA_DIR "/builddependencycollector/external/external1.h"), + id(TESTDATA_DIR "/builddependencycollector/external/external2.h"))))))); + EXPECT_CALL(mockClangPathWatcher, + updateIdPaths(ElementsAre(AllOf( + Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}), + Field(&ClangBackEnd::IdPaths::filePathIds, + UnorderedElementsAre( + id(TESTDATA_DIR "/builddependencycollector/system/system1.h"), + id(TESTDATA_DIR "/builddependencycollector/system/system2.h"))))))); EXPECT_CALL(mockBuildDependenciesStorage, updatePchCreationTimeStamp(Gt(0), Eq(1))); creator.doInMainThreadAfterFinished(); diff --git a/tests/unit/unittest/pchmanagerserver-test.cpp b/tests/unit/unittest/pchmanagerserver-test.cpp index 47b7d987ab7..9ece91234f4 100644 --- a/tests/unit/unittest/pchmanagerserver-test.cpp +++ b/tests/unit/unittest/pchmanagerserver-test.cpp @@ -25,11 +25,12 @@ #include "googletest.h" +#include "mockbuilddependenciesstorage.h" #include "mockclangpathwatcher.h" +#include "mockgeneratedfiles.h" #include "mockpchmanagerclient.h" #include "mockpchtaskgenerator.h" #include "mockprojectpartsmanager.h" -#include "mockgeneratedfiles.h" #include #include @@ -42,12 +43,13 @@ #include namespace { -using Utils::PathString; -using Utils::SmallString; -using ClangBackEnd::V2::FileContainer; -using ClangBackEnd::V2::FileContainers; +using ClangBackEnd::FilePathId; using ClangBackEnd::ProjectPartContainer; using ClangBackEnd::ProjectPartContainers; +using ClangBackEnd::V2::FileContainer; +using ClangBackEnd::V2::FileContainers; +using Utils::PathString; +using Utils::SmallString; using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts; class PchManagerServer : public ::testing::Test @@ -71,21 +73,27 @@ protected: NiceMock mockClangPathWatcher; NiceMock mockProjectPartsManager; NiceMock mockGeneratedFiles; + NiceMock mockBuildDependenciesStorage; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::PchManagerServer server{mockClangPathWatcher, mockPchTaskGenerator, mockProjectPartsManager, - mockGeneratedFiles}; + mockGeneratedFiles, + mockBuildDependenciesStorage}; NiceMock mockPchManagerClient; ClangBackEnd::ProjectPartId projectPartId1{1}; ClangBackEnd::ProjectPartId projectPartId2{2}; + ClangBackEnd::ProjectPartId projectPartId3{3}; + ClangBackEnd::ProjectPartId projectPartId4{4}; + ClangBackEnd::ProjectPartId projectPartId5{5}; + ClangBackEnd::ProjectPartId projectPartId6{6}; 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}}; + ClangBackEnd::IdPaths idPath{{projectPartId1, ClangBackEnd::SourceType::Source}, {1, 2}}; ProjectPartContainer projectPart1{ projectPartId1, {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, @@ -108,6 +116,50 @@ protected: Utils::Language::C, Utils::LanguageVersion::C11, Utils::LanguageExtension::All}; + ProjectPartContainer projectPart3{ + projectPartId3, + {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, + {{"DEFINE", "1", 1}}, + {{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, + {{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}}, + {id(header1Path)}, + {id(main1Path)}, + Utils::Language::C, + Utils::LanguageVersion::C11, + Utils::LanguageExtension::All}; + ProjectPartContainer projectPart4{ + projectPartId4, + {"-x", "c++-header", "-Wno-pragma-once-outside-header"}, + {{"DEFINE", "1", 1}}, + {{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, + {{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}}, + {id(header2Path)}, + {id(main2Path)}, + Utils::Language::C, + Utils::LanguageVersion::C11, + Utils::LanguageExtension::All}; + ProjectPartContainer projectPart5{ + projectPartId5, + {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, + {{"DEFINE", "1", 1}}, + {{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, + {{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}}, + {id(header1Path)}, + {id(main1Path)}, + Utils::Language::C, + Utils::LanguageVersion::C11, + Utils::LanguageExtension::All}; + ProjectPartContainer projectPart6{ + projectPartId6, + {"-x", "c++-header", "-Wno-pragma-once-outside-header"}, + {{"DEFINE", "1", 1}}, + {{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, + {{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}}, + {id(header2Path)}, + {id(main2Path)}, + Utils::Language::C, + Utils::LanguageVersion::C11, + Utils::LanguageExtension::All}; std::vector projectParts{projectPart1, projectPart2}; std::vector projectParts1{projectPart1}; std::vector projectParts2{projectPart2}; @@ -169,19 +221,68 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier) ClangBackEnd::PchManagerServer server{mockClangPathWatcher, mockPchTaskGenerator, mockProjectPartsManager, - mockGeneratedFiles}; + mockGeneratedFiles, + mockBuildDependenciesStorage}; } TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds) { - server.updateProjectParts( - ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}}); + server.updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage{ + {projectPart1, projectPart2, projectPart3, projectPart4, projectPart5, projectPart6}, + {"toolChainArgument"}}); - EXPECT_CALL(mockProjectPartsManager, projects(ElementsAre(projectPart1.projectPartId))) - .WillOnce(Return(std::vector{{projectPart1}})); - EXPECT_CALL(mockPchTaskGenerator, addProjectParts(ElementsAre(projectPart1), ElementsAre("toolChainArgument"))); + EXPECT_CALL(mockProjectPartsManager, + projects(ElementsAre(projectPart1.projectPartId, + projectPart2.projectPartId, + projectPart4.projectPartId, + projectPart5.projectPartId))) + .WillOnce(Return(std::vector{ + {projectPart1, projectPart2, projectPart4, projectPart5}})); + EXPECT_CALL(mockPchTaskGenerator, + addProjectParts(ElementsAre(projectPart1, projectPart2, projectPart4, projectPart5), + ElementsAre("toolChainArgument"))); - server.pathsWithIdsChanged({projectPartId1}); + server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::TopProjectInclude}, {}}, + {{projectPartId2, ClangBackEnd::SourceType::TopSystemInclude}, {}}, + {{projectPartId3, ClangBackEnd::SourceType::UserInclude}, {}}, + {{projectPartId4, ClangBackEnd::SourceType::ProjectInclude}, {}}, + {{projectPartId5, ClangBackEnd::SourceType::SystemInclude}, {}}, + {{projectPartId6, ClangBackEnd::SourceType::Source}, {}}}); +} + +TEST_F(PchManagerServer, DontUpdateProjectPartQueueByPathIdsIfItUserFile) +{ + server.updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage{{projectPart1, projectPart2}, + {"toolChainArgument"}}); + + EXPECT_CALL(mockProjectPartsManager, projects(_)).Times(0); + EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0); + + server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::UserInclude}, {}}, + {{projectPartId2, ClangBackEnd::SourceType::Source}, {}}}); +} + +TEST_F(PchManagerServer, ShortcutPrecompiledHeaderGenerationForUserIncludesAndSources) +{ + EXPECT_CALL(mockPchManagerClient, + precompiledHeadersUpdated( + Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds, + UnorderedElementsAre(projectPartId3, projectPartId6)))); + + server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::TopProjectInclude}, {}}, + {{projectPartId2, ClangBackEnd::SourceType::TopSystemInclude}, {}}, + {{projectPartId3, ClangBackEnd::SourceType::UserInclude}, {}}, + {{projectPartId4, ClangBackEnd::SourceType::ProjectInclude}, {}}, + {{projectPartId5, ClangBackEnd::SourceType::SystemInclude}, {}}, + {{projectPartId6, ClangBackEnd::SourceType::Source}, {}}}); +} +TEST_F(PchManagerServer, ResetTimeStampForChangedFilesInDatabase) +{ + EXPECT_CALL(mockBuildDependenciesStorage, + insertOrUpdateIndexingTimeStamps(ElementsAre(FilePathId{1}, FilePathId{3}, FilePathId{5}), + TypedEq(0))); + + server.pathsChanged({1, 3, 5}); } TEST_F(PchManagerServer, SetPchCreationProgress) @@ -214,7 +315,7 @@ TEST_F(PchManagerServer, RemoveToolChainsArguments) EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0); server.removeProjectParts(removeProjectPartsMessage.clone()); - server.pathsWithIdsChanged({projectPart1.projectPartId}); + server.pathsWithIdsChanged({{{projectPart1.projectPartId, ClangBackEnd::SourceType::Source}, {}}}); } TEST_F(PchManagerServer, DontGeneratePchIfGeneratedFilesAreNotValid) diff --git a/tests/unit/unittest/pchtaskgenerator-test.cpp b/tests/unit/unittest/pchtaskgenerator-test.cpp index cb9df32235c..b2293d6ec0a 100644 --- a/tests/unit/unittest/pchtaskgenerator-test.cpp +++ b/tests/unit/unittest/pchtaskgenerator-test.cpp @@ -84,7 +84,8 @@ protected: {2, SourceType::UserInclude, 1}, {3, SourceType::TopProjectInclude, 1}, {4, SourceType::SystemInclude, 1}, - {5, SourceType::TopSystemInclude, 1}}; + {5, SourceType::TopSystemInclude, 1}, + {6, SourceType::Source, 1}}; UsedMacros usedMacros{{"LIANG", 0},{"YI", 1}, {"ER", 2}, {"SAN", 3}, {"SE", 4}, {"WU", 5}}; BuildDependency buildDependency{firstSources, usedMacros, {}, {}, {}}; }; @@ -100,7 +101,10 @@ TEST_F(PchTaskGenerator, AddProjectParts) Field(&PchTaskSet::system, AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})), Field(&PchTask::includes, ElementsAre(5)), - Field(&PchTask::sources, IsEmpty()), + Field(&PchTask::watchedSystemIncludes, IsEmpty()), + Field(&PchTask::watchedProjectIncludes, IsEmpty()), + Field(&PchTask::watchedUserIncludes, IsEmpty()), + Field(&PchTask::watchedUserSources, IsEmpty()), Field(&PchTask::compilerMacros, ElementsAre(CompilerMacro{"SE", "4", 4}, CompilerMacro{"WU", "5", 5})), Field(&PchTask::systemIncludeSearchPaths, @@ -117,7 +121,10 @@ TEST_F(PchTaskGenerator, AddProjectParts) &PchTaskSet::project, AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})), Field(&PchTask::includes, ElementsAre(3)), - Field(&PchTask::sources, ElementsAre(1, 3, 4, 5)), + Field(&PchTask::watchedSystemIncludes, ElementsAre(4, 5)), + Field(&PchTask::watchedProjectIncludes, ElementsAre(1, 3)), + Field(&PchTask::watchedUserIncludes, ElementsAre(2)), + Field(&PchTask::watchedUserSources, ElementsAre(6)), Field(&PchTask::compilerMacros, ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3})), Field(&PchTask::systemIncludeSearchPaths, diff --git a/tests/unit/unittest/pchtaskqueue-test.cpp b/tests/unit/unittest/pchtaskqueue-test.cpp index 1754cea5623..0715602f97d 100644 --- a/tests/unit/unittest/pchtaskqueue-test.cpp +++ b/tests/unit/unittest/pchtaskqueue-test.cpp @@ -67,6 +67,9 @@ protected: PchTask systemTask1{1, {1, 2}, {1, 2}, + {2, 3}, + {3, 4}, + {6, 7}, {{"YI", "1", 1}, {"SAN", "3", 3}}, {{"LIANG", 0}, {"YI", 1}}, {"--yi"}, @@ -75,6 +78,9 @@ protected: PchTask systemTask2{2, {1, 2}, {1, 2}, + {2, 3}, + {3, 4}, + {6, 7}, {{"YI", "1", 1}, {"SAN", "3", 3}}, {{"LIANG", 0}, {"YI", 1}}, {"--yi"}, @@ -83,6 +89,9 @@ protected: PchTask systemTask2b{2, {3, 4}, {3, 4}, + {5, 6}, + {4, 7}, + {8, 9}, {{"YI", "1", 1}, {"SAN", "3", 3}}, {{"LIANG", 0}, {"YI", 1}}, {"--yi"}, @@ -91,6 +100,9 @@ protected: PchTask systemTask3{3, {1, 2}, {1, 2}, + {2, 3}, + {3, 4}, + {6, 7}, {{"YI", "1", 1}, {"SAN", "3", 3}}, {{"LIANG", 0}, {"YI", 1}}, {"--yi"}, @@ -99,6 +111,9 @@ protected: PchTask projectTask1{1, {11, 12}, {11, 12}, + {12, 13}, + {13, 14}, + {16, 17}, {{"SE", "4", 4}, {"WU", "5", 5}}, {{"ER", 2}, {"SAN", 3}}, {"--yi"}, @@ -107,6 +122,9 @@ protected: PchTask projectTask2{2, {11, 12}, {11, 12}, + {12, 13}, + {13, 14}, + {16, 17}, {{"SE", "4", 4}, {"WU", "5", 5}}, {{"ER", 2}, {"SAN", 3}}, {"--yi"}, @@ -115,6 +133,9 @@ protected: PchTask projectTask2b{2, {21, 22}, {11, 12}, + {22, 23}, + {23, 24}, + {26, 27}, {{"SE", "4", 4}, {"WU", "5", 5}}, {{"ER", 2}, {"SAN", 3}}, {"--yi"}, @@ -123,6 +144,9 @@ protected: PchTask projectTask3{3, {21, 22}, {21, 22}, + {22, 23}, + {23, 24}, + {26, 27}, {{"SE", "4", 4}, {"WU", "5", 5}}, {{"ER", 2}, {"SAN", 3}}, {"--yi"}, @@ -131,6 +155,9 @@ protected: PchTask systemTask4{{1, 3}, {1, 2}, {1, 2}, + {2, 3}, + {3, 4}, + {5, 8}, {{"YI", "1", 1}, {"SAN", "3", 3}}, {{"LIANG", 0}, {"YI", 1}}, {"--yi"}, diff --git a/tests/unit/unittest/pchtasksmerger-test.cpp b/tests/unit/unittest/pchtasksmerger-test.cpp index 076e1415b26..28f9593ad45 100644 --- a/tests/unit/unittest/pchtasksmerger-test.cpp +++ b/tests/unit/unittest/pchtasksmerger-test.cpp @@ -54,7 +54,10 @@ protected: ClangBackEnd::PchTasksMerger merger{mockPchTaskQueue}; PchTask systemTask1{1, {1, 2}, - {1, 2, 3}, + {}, + {}, + {}, + {}, {{"YI", "1", 1}, {"SAN", "3", 3}}, {"YI", "LIANG"}, {"--yi"}, @@ -66,6 +69,9 @@ protected: PchTask projectTask1{1, {11, 12}, {11, 12}, + {21, 22}, + {31, 32}, + {41, 42}, {{"SE", "4", 4}, {"WU", "5", 5}}, {"ER", "SAN"}, {"--yi"}, @@ -75,7 +81,10 @@ protected: {"/to/path2", 2, IncludeSearchPathType::User}}}; PchTask systemTask2{2, {11, 12}, - {11, 12, 13}, + {}, + {}, + {}, + {}, {{"SE", "4", 4}, {"WU", "5", 5}}, {"ER", "SAN"}, {"--yi"}, @@ -87,6 +96,9 @@ protected: PchTask projectTask2{2, {11, 12}, {11, 12}, + {21, 22}, + {31, 32}, + {41, 42}, {{"SE", "4", 4}, {"WU", "5", 5}}, {"ER", "SAN"}, {"--yi"}, @@ -97,7 +109,10 @@ protected: {"/to/path2", 2, IncludeSearchPathType::User}}}; PchTask systemTask3{3, {1, 2}, - {1, 2}, + {}, + {}, + {}, + {}, {{"YI", "2", 1}, {"SAN", "3", 3}}, {"YI", "LIANG"}, {"--yi"}, @@ -268,18 +283,25 @@ TEST_F(PchTasksMerger, DontMergeIncludes) ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2)); } -TEST_F(PchTasksMerger, MergeAllIncludes) +TEST_F(PchTasksMerger, DontMergeWatchedSystemSources) { Merger::mergePchTasks(systemTask1, systemTask2); - ASSERT_THAT(systemTask1.sources, ElementsAre(1, 2, 3, 11, 12, 13)); + ASSERT_THAT(systemTask1.watchedSystemIncludes, IsEmpty()); } -TEST_F(PchTasksMerger, DontAllMergeIncludes) +TEST_F(PchTasksMerger, DontMergeWatchedProjectSources) { Merger::mergePchTasks(systemTask1, systemTask3); - ASSERT_THAT(systemTask1.sources, ElementsAre(1, 2, 3)); + ASSERT_THAT(systemTask1.watchedProjectIncludes, IsEmpty()); +} + +TEST_F(PchTasksMerger, DontMergeWatchedUserSources) +{ + Merger::mergePchTasks(systemTask1, systemTask3); + + ASSERT_THAT(systemTask1.watchedUserSources, IsEmpty()); } TEST_F(PchTasksMerger, MergeProjectIds) diff --git a/tests/unit/unittest/projectpartsstorage-test.cpp b/tests/unit/unittest/projectpartsstorage-test.cpp index 3c13f33ad61..ba1b6f70630 100644 --- a/tests/unit/unittest/projectpartsstorage-test.cpp +++ b/tests/unit/unittest/projectpartsstorage-test.cpp @@ -463,7 +463,6 @@ protected: Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; Storage storage{database}; - ClangBackEnd::SymbolStorage<> symbolStorage{database}; ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database}; }; @@ -505,13 +504,13 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectParts) TEST_F(ProjectPartsStorageSlow, ResetDependentIndexingTimeStamps) { - symbolStorage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 34); + buildDependenciesStorage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 34); buildDependenciesStorage.insertOrUpdateSourceDependencies( {{3, 1}, {4, 1}, {1, 2}, {7, 5}, {8, 6}, {6, 5}, {9, 10}}); storage.resetIndexingTimeStamps({projectPart1, projectPart2}); - ASSERT_THAT(symbolStorage.fetchIndexingTimeStamps(), + ASSERT_THAT(buildDependenciesStorage.fetchIndexingTimeStamps(), ElementsAre(SourceTimeStamp{1, 0}, SourceTimeStamp{2, 0}, SourceTimeStamp{3, 0}, diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp index 16e0fc81b09..3e0359cd8d6 100644 --- a/tests/unit/unittest/symbolindexer-test.cpp +++ b/tests/unit/unittest/symbolindexer-test.cpp @@ -116,11 +116,11 @@ protected: .WillByDefault(Return(artefact)); ON_CALL(mockBuildDependenciesStorage, fetchLowestLastModifiedTime(A())).WillByDefault(Return(-1)); ON_CALL(mockCollector, collectSymbols()).WillByDefault(Return(true)); - ON_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds)) + ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(sourceFileIds)) .WillByDefault(Return(sourceFileIds)); - ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(sourceFileIds[0]))) + ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(ElementsAre(sourceFileIds[0]))) .WillByDefault(Return(FilePathIds{sourceFileIds[0]})); - ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(main1PathId))) + ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(ElementsAre(main1PathId))) .WillByDefault(Return(FilePathIds{main1PathId})); mockCollector.setIsUsed(false); @@ -879,16 +879,16 @@ TEST_F(SymbolIndexer, UpdateProjectPartsFetchIncludedIndexingTimeStamps) Utils::LanguageVersion::CXX14, Utils::LanguageExtension::None}; - EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(main1PathId))) + EXPECT_CALL(mockBuildDependenciesStorage, fetchIncludedIndexingTimeStamps(Eq(main1PathId))) .WillOnce(Return(dependentSourceTimeStamps1)); EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps1)); - EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(main2PathId))) + EXPECT_CALL(mockBuildDependenciesStorage, fetchIncludedIndexingTimeStamps(Eq(main2PathId))) .WillOnce(Return(dependentSourceTimeStamps2)); EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps2)); EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses1)); - EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1)); + EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1)); EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses2)); - EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2)); + EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2)); indexer.updateProjectParts({projectPart}); } @@ -917,642 +917,6 @@ TEST_F(SymbolIndexer, DependentSourceAreUpToDate) indexer.updateProjectParts({projectPart1}); } -TEST_F(SymbolIndexer, SourcesAreWatched) -{ - using ClangBackEnd::IdPaths; - InSequence s; - FilePathIds sourcePathIds{4, 6, 8}; - - EXPECT_CALL(mockBuildDependenciesStorage, fetchPchSources(projectPart1.projectPartId)) - .WillOnce(Return(sourcePathIds)); - EXPECT_CALL(mockPathWatcher, - updateIdPaths(ElementsAre(AllOf(Field(&IdPaths::id, projectPart1.projectPartId), - Field(&IdPaths::filePathIds, sourcePathIds))))); - - indexer.updateProjectParts({projectPart1}); -} - -TEST_F(SymbolIndexer, CallSetNotifier) -{ - EXPECT_CALL(mockPathWatcher, setNotifier(_)); - - ClangBackEnd::SymbolIndexer indexer{indexerQueue, - mockSymbolStorage, - mockBuildDependenciesStorage, - mockPrecompiledHeaderStorage, - mockPathWatcher, - filePathCache, - fileStatusCache, - mockSqliteTransactionBackend, - mockProjectPartsStorage, - mockModifiedTimeChecker, - testEnvironment}; -} - -TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage) -{ - EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0])); - EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[1])); - - indexer.pathsChanged(sourceFileIds); -} - -TEST_F(SymbolIndexer, PathChangedCallsFetchSourcePathIds) -{ - InSequence s; - - EXPECT_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds)) - .WillOnce(Return(FilePathIds{2, 6, 5})); - EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{2})); - EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{6})); - EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{5})); - - indexer.pathsChanged(sourceFileIds); -} - -TEST_F(SymbolIndexer, PathChangedFetchIncludedIndexingTimeStamps) -{ - InSequence s; - ProjectPartContainer projectPart{1, - {"-Wno-pragma-once-outside-header"}, - {{"BAR", "1", 1}, {"FOO", "1", 2}}, - Utils::clone(systemIncludeSearchPaths), - Utils::clone(projectIncludeSearchPaths), - {header1PathId}, - {main1PathId, main2PathId}, - Utils::Language::Cxx, - Utils::LanguageVersion::CXX14, - Utils::LanguageExtension::None}; - - EXPECT_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillOnce(Return(FilePathIds{1, 2})); - EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(1))) - .WillOnce(Return(dependentSourceTimeStamps1)); - EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(2))) - .WillOnce(Return(dependentSourceTimeStamps2)); - EXPECT_CALL(mockCollector, fileStatuses()).WillOnce(ReturnRef(fileStatuses1)); - EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1)); - EXPECT_CALL(mockCollector, fileStatuses()).WillOnce(ReturnRef(fileStatuses2)); - EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2)); - - indexer.pathsChanged({1, 3}); -} - -TEST_F(SymbolIndexer, PathChangedFetchesDependentSourceIdsFromStorage) -{ - EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0])); - EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[1])); - - indexer.pathsChanged(sourceFileIds); -} - -TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder) -{ - InSequence s; - - EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin()); - EXPECT_CALL(mockProjectPartsStorage, - fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) - .WillOnce(Return(artefact)); - EXPECT_CALL(mockSqliteTransactionBackend, commit()); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))); - EXPECT_CALL(mockCollector, - setFile(Eq(sourceFileIds[0]), - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes")))); - EXPECT_CALL(mockCollector, collectSymbols()); - EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)); - EXPECT_CALL(mockSqliteTransactionBackend, commit()); - - indexer.pathsChanged({sourceFileIds[0]}); -} - -TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath) -{ - InSequence s; - - EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin()); - EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0])) - .WillOnce(Return(nullArtefact)); - EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(_)).Times(0); - EXPECT_CALL(mockCollector, setFile(_, _)).Times(0); - EXPECT_CALL(mockCollector, collectSymbols()).Times(0); - EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(_, _)).Times(0); - EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0); - - indexer.pathsChanged({sourceFileIds[0]}); -} - -TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasNoError) -{ - InSequence s; - - EXPECT_CALL(mockProjectPartsStorage, - fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) - .WillOnce(Return(artefact)); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))) - .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"})); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes"), - "-Xclang", - "-include-pch", - "-Xclang", - toNativePath("/project/pch")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)); - EXPECT_CALL(mockCollector, collectSymbols()).Times(0); - - indexer.pathsChanged({sourceFileIds[0]}); -} - -TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectPch) -{ - InSequence s; - - EXPECT_CALL(mockProjectPartsStorage, - fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) - .WillOnce(Return(artefact)); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))) - .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"})); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes"), - "-Xclang", - "-include-pch", - "-Xclang", - toNativePath("/project/pch")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes"), - "-Xclang", - "-include-pch", - "-Xclang", - toNativePath("/system/pch")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)); - EXPECT_CALL(mockCollector, collectSymbols()).Times(0); - - indexer.pathsChanged({sourceFileIds[0]}); -} - -TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectAndSystemPch) -{ - InSequence s; - - EXPECT_CALL(mockProjectPartsStorage, - fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) - .WillOnce(Return(artefact)); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))) - .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"})); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes"), - "-Xclang", - "-include-pch", - "-Xclang", - toNativePath("/project/pch")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes"), - "-Xclang", - "-include-pch", - "-Xclang", - toNativePath("/system/pch")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)); - - indexer.pathsChanged({sourceFileIds[0]}); -} - -TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasOnlyError) -{ - InSequence s; - - EXPECT_CALL(mockProjectPartsStorage, - fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) - .WillOnce(Return(artefact)); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))) - .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"})); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes"), - "-Xclang", - "-include-pch", - "-Xclang", - toNativePath("/project/pch")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes"), - "-Xclang", - "-include-pch", - "-Xclang", - toNativePath("/system/pch")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0); - - indexer.pathsChanged({sourceFileIds[0]}); -} - -TEST_F(SymbolIndexer, PathsChangedCallsGetsSystemPchPathsAndHasErrorWithProjectPch) -{ - InSequence s; - - EXPECT_CALL(mockProjectPartsStorage, - fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) - .WillOnce(Return(artefact)); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))) - .WillOnce(Return(ClangBackEnd::PchPaths{{}, "/system/pch"})); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes"), - "-Xclang", - "-include-pch", - "-Xclang", - toNativePath("/system/pch")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)); - EXPECT_CALL(mockCollector, collectSymbols()).Times(0); - - indexer.pathsChanged({sourceFileIds[0]}); -} - -TEST_F(SymbolIndexer, PathsChangedCallsGetsNoPchPathsAndHasErrors) -{ - InSequence s; - - EXPECT_CALL(mockProjectPartsStorage, - fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) - .WillOnce(Return(artefact)); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))); - EXPECT_CALL(mockCollector, - setFile(sourceFileIds[0], - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes")))); - EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true)); - EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)); - EXPECT_CALL(mockCollector, collectSymbols()).Times(0); - - indexer.pathsChanged({sourceFileIds[0]}); -} - -TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader) -{ - ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) - .WillByDefault(Return(artefact)); - ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))) - .WillByDefault(Return(pchPaths)); - std::vector symbolIndexerTask; - - EXPECT_CALL(mockCollector, - setFile(Eq(sourceFileIds[0]), - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes"), - "-Xclang", - "-include-pch", - "-Xclang", - toNativePath("/project/pch")))); - - indexer.pathsChanged({sourceFileIds[0]}); -} - -TEST_F(SymbolIndexer, UpdateChangedPathIsNotUsingPrecompiledHeaderIfItNotExists) -{ - ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) - .WillByDefault(Return(artefact)); - std::vector symbolIndexerTask; - - EXPECT_CALL(mockCollector, - setFile(Eq(sourceFileIds[0]), - ElementsAre("clang++", - "-w", - "-DFOO", - "-DNOMINMAX", - "-x", - "c++", - "-std=c++14", - "-nostdinc", - "-nostdinc++", - "-DBAR=1", - "-DFOO=1", - "-isystem", - toNativePath(TESTDATA_DIR "/preincludes"), - "-I", - toNativePath("/project/includes"), - "-I", - toNativePath("/other/project/includes"), - "-isystem", - toNativePath(TESTDATA_DIR), - "-isystem", - toNativePath("/other/includes"), - "-isystem", - toNativePath("/includes")))); - - indexer.pathsChanged({sourceFileIds[0]}); -} - - TEST_F(SymbolIndexer, CompilerMacrosAndIncludeSearchPathsAreNotDifferent) { ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(A())) @@ -1660,7 +1024,8 @@ TEST_F(SymbolIndexer, PathsChangedUpdatesFileStatusCache) { auto sourceId = filePathId(TESTDATA_DIR "/symbolindexer_pathChanged.cpp"); ON_CALL(mockFileSystem, lastModified(Eq(sourceId))).WillByDefault(Return(65)); - ON_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillByDefault(Return(FilePathIds{sourceId})); + ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(_)) + .WillByDefault(Return(FilePathIds{sourceId})); indexer.pathsChanged({sourceId}); diff --git a/tests/unit/unittest/symbolstorage-test.cpp b/tests/unit/unittest/symbolstorage-test.cpp index a29b7f92aa1..c480296f120 100644 --- a/tests/unit/unittest/symbolstorage-test.cpp +++ b/tests/unit/unittest/symbolstorage-test.cpp @@ -69,10 +69,6 @@ protected: MockSqliteWriteStatement &insertNewLocationsInLocationsStatement = storage.insertNewLocationsInLocationsStatement; MockSqliteWriteStatement &deleteNewSymbolsTableStatement = storage.deleteNewSymbolsTableStatement; MockSqliteWriteStatement &deleteNewLocationsTableStatement = storage.deleteNewLocationsTableStatement; - MockSqliteWriteStatement &inserOrUpdateIndexingTimesStampStatement = storage.inserOrUpdateIndexingTimesStampStatement; - MockSqliteReadStatement &fetchIndexingTimeStampsStatement = storage.fetchIndexingTimeStampsStatement; - MockSqliteReadStatement &fetchIncludedIndexingTimeStampsStatement = storage.fetchIncludedIndexingTimeStampsStatement; - MockSqliteReadStatement &fetchDependentSourceIdsStatement = storage.fetchDependentSourceIdsStatement; SymbolEntries symbolEntries{{1, {"functionUSR", "function", SymbolKind::Function}}, {2, {"function2USR", "function2", SymbolKind::Function}}}; SourceLocationEntries sourceLocations{{1, 3, {42, 23}, SourceLocationKind::Declaration}, @@ -192,145 +188,4 @@ TEST_F(SymbolStorage, AddTablesInConstructor) Storage storage{mockDatabase}; } -TEST_F(SymbolStorage, FetchIndexingTimeStampsIsBusy) -{ - InSequence s; - - EXPECT_CALL(mockDatabase, deferredBegin()); - EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024)) - .WillOnce(Throw(Sqlite::StatementIsBusy{""})); - EXPECT_CALL(mockDatabase, rollback()); - EXPECT_CALL(mockDatabase, deferredBegin()); - EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024)); - EXPECT_CALL(mockDatabase, commit()); - - storage.fetchIndexingTimeStamps(); -} - -TEST_F(SymbolStorage, InsertIndexingTimeStamp) -{ - ClangBackEnd::FileStatuses fileStatuses{{1, 0, 34}, {2, 0, 37}}; - - EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq(1), TypedEq(34))); - EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq(2), TypedEq(37))); - - storage.insertOrUpdateIndexingTimeStamps(fileStatuses); -} - -TEST_F(SymbolStorage, InsertIndexingTimeStampsIsBusy) -{ - InSequence s; - - EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""})); - EXPECT_CALL(mockDatabase, immediateBegin()); - EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq(1), TypedEq(34))); - EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq(2), TypedEq(34))); - EXPECT_CALL(mockDatabase, commit()); - - storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34); -} - -TEST_F(SymbolStorage, FetchIncludedIndexingTimeStampsIsBusy) -{ - InSequence s; - - EXPECT_CALL(mockDatabase, deferredBegin()); - EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement, - valuesReturnSourceTimeStamps(1024, TypedEq(1))) - .WillOnce(Throw(Sqlite::StatementIsBusy{""})); - EXPECT_CALL(mockDatabase, rollback()); - EXPECT_CALL(mockDatabase, deferredBegin()); - EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement, - valuesReturnSourceTimeStamps(1024, TypedEq(1))); - EXPECT_CALL(mockDatabase, commit()); - - storage.fetchIncludedIndexingTimeStamps(1); -} - -TEST_F(SymbolStorage, FetchDependentSourceIdsIsBusy) -{ - InSequence s; - - EXPECT_CALL(mockDatabase, deferredBegin()); - EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq(3))); - EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq(2))) - .WillOnce(Throw(Sqlite::StatementIsBusy{""})); - EXPECT_CALL(mockDatabase, rollback()); - EXPECT_CALL(mockDatabase, deferredBegin()); - EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq(3))); - EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq(2))); - EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq(7))); - EXPECT_CALL(mockDatabase, commit()); - - storage.fetchDependentSourceIds({3, 2, 7}); -} - -class SymbolStorageSlow : public testing::Test -{ -protected: - Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; - ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; - ClangBackEnd::SymbolStorage<> storage{database}; - ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database}; -}; - -TEST_F(SymbolStorageSlow, InsertIndexingTimeStamps) -{ - storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34); - - ASSERT_THAT(storage.fetchIndexingTimeStamps(), - ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 34})); -} - -TEST_F(SymbolStorageSlow, UpdateIndexingTimeStamps) -{ - storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34); - - storage.insertOrUpdateIndexingTimeStamps({1}, 37); - - ASSERT_THAT(storage.fetchIndexingTimeStamps(), - ElementsAre(SourceTimeStamp{1, 37}, SourceTimeStamp{2, 34})); -} - -TEST_F(SymbolStorageSlow, InsertIndexingTimeStamp) -{ - storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 37}}); - - ASSERT_THAT(storage.fetchIndexingTimeStamps(), - ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37})); -} - -TEST_F(SymbolStorageSlow, UpdateIndexingTimeStamp) -{ - storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 34}}); - - storage.insertOrUpdateIndexingTimeStamps({{2, 0, 37}}); - - ASSERT_THAT(storage.fetchIndexingTimeStamps(), - ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37})); -} - -TEST_F(SymbolStorageSlow, FetchIncludedIndexingTimeStamps) -{ - storage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5}, 34); - buildDependenciesStorage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {3, 4}, {5, 3}}); - - auto timeStamps = storage.fetchIncludedIndexingTimeStamps(1); - - ASSERT_THAT(timeStamps, - ElementsAre(SourceTimeStamp{1, 34}, - SourceTimeStamp{2, 34}, - SourceTimeStamp{3, 34}, - SourceTimeStamp{4, 34})); -} - -TEST_F(SymbolStorageSlow, FetchDependentSourceIds) -{ - buildDependenciesStorage.insertOrUpdateSourceDependencies( - {{1, 2}, {1, 3}, {2, 3}, {4, 2}, {5, 6}, {7, 6}}); - - auto sourceIds = storage.fetchDependentSourceIds({3, 2, 7}); - - ASSERT_THAT(sourceIds, ElementsAre(FilePathId{1}, FilePathId{4}, FilePathId{7})); -} } // namespace diff --git a/tests/unit/unittest/usedmacrofilter-test.cpp b/tests/unit/unittest/usedmacrofilter-test.cpp index 85e1bb59b50..0e6be5680eb 100644 --- a/tests/unit/unittest/usedmacrofilter-test.cpp +++ b/tests/unit/unittest/usedmacrofilter-test.cpp @@ -97,8 +97,14 @@ TEST_F(UsedMacroFilter, Sources) { ClangBackEnd::UsedMacroFilter filter(sources, usedMacros, compileMacros); - ASSERT_THAT(filter.sources, - ElementsAre(FilePathId{2}, FilePathId{3}, FilePathId{4}, FilePathId{5})); + ASSERT_THAT(filter.sources, ElementsAre(FilePathId{6})); +} + +TEST_F(UsedMacroFilter, UserIncludes) +{ + ClangBackEnd::UsedMacroFilter filter(sources, usedMacros, compileMacros); + + ASSERT_THAT(filter.userIncludes, ElementsAre(FilePathId{1})); } TEST_F(UsedMacroFilter, SystemUsedMacros)