diff --git a/src/libs/clangsupport/filecontainerv2.h b/src/libs/clangsupport/filecontainerv2.h index aa7248fb5e2..e6e8c6622f4 100644 --- a/src/libs/clangsupport/filecontainerv2.h +++ b/src/libs/clangsupport/filecontainerv2.h @@ -27,6 +27,7 @@ #include "clangsupport_global.h" #include "filepath.h" +#include "filepathid.h" #include @@ -39,13 +40,15 @@ public: FileContainer() = default; FileContainer(FilePath &&filePath, + FilePathId filePathId, Utils::SmallString &&unsavedFileContent, Utils::SmallStringVector &&commandLineArguments = {}, quint32 documentRevision = 0) - : filePath(std::move(filePath)), - unsavedFileContent(std::move(unsavedFileContent)), - commandLineArguments(std::move(commandLineArguments)), - documentRevision(documentRevision) + : filePath(std::move(filePath)) + , filePathId(filePathId) + , unsavedFileContent(std::move(unsavedFileContent)) + , commandLineArguments(std::move(commandLineArguments)) + , documentRevision(documentRevision) { } @@ -81,16 +84,11 @@ public: < std::tie(second.filePath, second.documentRevision, second.unsavedFileContent, second.commandLineArguments); } - FileContainer clone() const - { - return FileContainer(filePath.clone(), - unsavedFileContent.clone(), - commandLineArguments.clone(), - documentRevision); - } + FileContainer clone() const { return *this; } public: FilePath filePath; + FilePathId filePathId; Utils::SmallString unsavedFileContent; Utils::SmallStringVector commandLineArguments; quint32 documentRevision = 0; diff --git a/src/libs/clangsupport/filepathcache.h b/src/libs/clangsupport/filepathcache.h index ecc84570285..541769b0b51 100644 --- a/src/libs/clangsupport/filepathcache.h +++ b/src/libs/clangsupport/filepathcache.h @@ -67,13 +67,20 @@ public: FilePathCache(FilePathStorage &filePathStorage) : m_filePathStorage(filePathStorage) { - m_directoryPathCache.populate(filePathStorage.fetchAllDirectories()); - m_fileNameCache.populate(filePathStorage.fetchAllSources()); + populateIfEmpty(); } FilePathCache(FilePathCache &&) = default; FilePathCache &operator=(FilePathCache &&) = default; + void populateIfEmpty() + { + if (m_fileNameCache.isEmpty()) { + m_directoryPathCache.populate(m_filePathStorage.fetchAllDirectories()); + m_fileNameCache.populate(m_filePathStorage.fetchAllSources()); + } + } + template Cache clone() { @@ -126,8 +133,7 @@ public: return FileNameEntry{entry.sourceName, entry.directoryId}; }; - FileNameEntry entry = m_fileNameCache.string(filePathId.filePathId, - fetchSoureNameAndDirectoryId); + auto entry = m_fileNameCache.string(filePathId.filePathId, fetchSoureNameAndDirectoryId); auto fetchDirectoryPath = [&] (int id) { return m_filePathStorage.fetchDirectoryPath(id); }; @@ -157,9 +163,6 @@ public: return FileNameEntry{entry.sourceName, entry.directoryId}; }; - FileNameEntry entry = m_fileNameCache.string(filePathId.filePathId, - fetchSoureNameAndDirectoryId); - return m_fileNameCache.string(filePathId.filePathId, fetchSoureNameAndDirectoryId).directoryId; } diff --git a/src/libs/clangsupport/filepathcaching.cpp b/src/libs/clangsupport/filepathcaching.cpp index e2b23e7ad66..f6d9ba9691d 100644 --- a/src/libs/clangsupport/filepathcaching.cpp +++ b/src/libs/clangsupport/filepathcaching.cpp @@ -57,6 +57,11 @@ void FilePathCaching::addFilePaths(const FilePaths &filePaths) m_cache.addFilePaths(filePaths); } +void FilePathCaching::populateIfEmpty() +{ + m_cache.populateIfEmpty(); +} + FilePathId CopyableFilePathCaching::filePathId(FilePathView filePath) const { return m_cache.filePathId(filePath); @@ -87,4 +92,9 @@ void CopyableFilePathCaching::addFilePaths(const FilePaths &filePaths) m_cache.addFilePaths(filePaths); } +void CopyableFilePathCaching::populateIfEmpty() +{ + m_cache.populateIfEmpty(); +} + } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/filepathcaching.h b/src/libs/clangsupport/filepathcaching.h index 17f1fb1d0e3..7c1f3434019 100644 --- a/src/libs/clangsupport/filepathcaching.h +++ b/src/libs/clangsupport/filepathcaching.h @@ -56,6 +56,7 @@ public: Utils::PathString directoryPath(DirectoryPathId directoryPathId) const override; DirectoryPathId directoryPathId(FilePathId filePathId) const override; void addFilePaths(const ClangBackEnd::FilePaths &filePaths) override; + void populateIfEmpty() override; private: Factory m_factory; @@ -80,6 +81,7 @@ public: Utils::PathString directoryPath(DirectoryPathId directoryPathId) const override; DirectoryPathId directoryPathId(FilePathId filePathId) const override; void addFilePaths(const ClangBackEnd::FilePaths &filePaths) override; + void populateIfEmpty() override; private: Cache m_cache; diff --git a/src/libs/clangsupport/filepathcachinginterface.h b/src/libs/clangsupport/filepathcachinginterface.h index 67e30d1c5ce..69be405d37d 100644 --- a/src/libs/clangsupport/filepathcachinginterface.h +++ b/src/libs/clangsupport/filepathcachinginterface.h @@ -45,6 +45,7 @@ public: virtual DirectoryPathId directoryPathId(FilePathId filePathId) const = 0; virtual Utils::PathString directoryPath(DirectoryPathId directoryPathId) const = 0; virtual void addFilePaths(const ClangBackEnd::FilePaths &filePaths) = 0; + virtual void populateIfEmpty() = 0; template FilePathIds filePathIds(Container &&filePaths) const diff --git a/src/libs/clangsupport/generatedfiles.cpp b/src/libs/clangsupport/generatedfiles.cpp index 644137886ba..22b1e8044a9 100644 --- a/src/libs/clangsupport/generatedfiles.cpp +++ b/src/libs/clangsupport/generatedfiles.cpp @@ -53,7 +53,7 @@ void GeneratedFiles::update(const V2::FileContainers &fileContainers) V2::FileContainers unionFileContainers; unionFileContainers.reserve(m_fileContainers.size() + fileContainers.size()); - auto compare = [] (const V2::FileContainer &first, const V2::FileContainer &second) { + auto compare = [](const V2::FileContainer &first, const V2::FileContainer &second) { return first.filePath < second.filePath; }; @@ -69,10 +69,7 @@ void GeneratedFiles::update(const V2::FileContainers &fileContainers) class Compare { public: - bool operator()(const FilePath &first, const FilePath &second) - { - return first < second; - } + bool operator()(const FilePath &first, const FilePath &second) { return first < second; } bool operator()(const V2::FileContainer &first, const V2::FileContainer &second) { return first.filePath < second.filePath; @@ -116,4 +113,16 @@ const V2::FileContainers &GeneratedFiles::fileContainers() const return m_fileContainers; } +FilePathIds GeneratedFiles::filePathIds() const +{ + auto ids = Utils::transform(m_fileContainers, + [](const V2::FileContainer &fileContainer) { + return fileContainer.filePathId; + }); + + std::sort(ids.begin(), ids.end()); + + return ids; +} + } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/generatedfiles.h b/src/libs/clangsupport/generatedfiles.h index 933b0d111bf..3e87048be9c 100644 --- a/src/libs/clangsupport/generatedfiles.h +++ b/src/libs/clangsupport/generatedfiles.h @@ -38,6 +38,7 @@ public: bool isValid() const; const V2::FileContainers &fileContainers() const; + FilePathIds filePathIds() const; private: V2::FileContainers m_fileContainers; diff --git a/src/libs/clangsupport/generatedfilesinterface.h b/src/libs/clangsupport/generatedfilesinterface.h index 85a50ffa387..72a1dfccfb4 100644 --- a/src/libs/clangsupport/generatedfilesinterface.h +++ b/src/libs/clangsupport/generatedfilesinterface.h @@ -38,6 +38,7 @@ public: virtual bool isValid() const = 0; virtual const V2::FileContainers &fileContainers() const = 0; + virtual FilePathIds filePathIds() const = 0; protected: ~GeneratedFilesInterface() = default; diff --git a/src/libs/clangsupport/projectpartsstorage.h b/src/libs/clangsupport/projectpartsstorage.h index 4ff1789c93b..492a46f648c 100644 --- a/src/libs/clangsupport/projectpartsstorage.h +++ b/src/libs/clangsupport/projectpartsstorage.h @@ -109,26 +109,33 @@ public: } } + ProjectPartId fetchProjectPartIdUnguarded(Utils::SmallStringView projectPartName) const override + { + auto optionalProjectPartId = fetchProjectPartIdStatement.template value( + projectPartName); + + if (optionalProjectPartId) { + return *optionalProjectPartId; + } else { + insertProjectPartNameStatement.write(projectPartName); + + return static_cast(database.lastInsertedRowId()); + } + + return {}; + } + ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) const override { try { Sqlite::DeferredTransaction transaction{database}; - ProjectPartId projectPartId; - auto optionalProjectPartId = fetchProjectPartIdStatement.template value( - projectPartName); - - if (optionalProjectPartId) { - projectPartId = *optionalProjectPartId; - } else { - insertProjectPartNameStatement.write(projectPartName); - - projectPartId = static_cast(database.lastInsertedRowId()); - } + ProjectPartId projectPartId = fetchProjectPartIdUnguarded(projectPartName); transaction.commit(); return projectPartId; + } catch (const Sqlite::StatementIsBusy &) { return fetchProjectPartId(projectPartName); } @@ -330,6 +337,23 @@ public: Utils::SmallString::number(projectPartId.projectPathId)); } + Internal::ProjectPartNameIds fetchAllProjectPartNamesAndIds() const + { + try { + Sqlite::DeferredTransaction transaction{database}; + + ReadStatement &statement = fetchAllProjectPartNamesAndIdsStatement; + + auto values = statement.template values(256); + + transaction.commit(); + + return values; + } catch (const Sqlite::StatementIsBusy &) { + return fetchAllProjectPartNamesAndIds(); + } + } + public: Sqlite::ImmediateNonThrowingDestructorTransaction transaction; Database &database; @@ -383,5 +407,7 @@ public: "SELECT projectPchBuildTime FROM precompiledHeaders WHERE projectPartId = ?", database}; WriteStatement resetDependentIndexingTimeStampsStatement{ "UPDATE fileStatuses SET indexingTimeStamp = NULL WHERE sourceId = ?", database}; + mutable ReadStatement fetchAllProjectPartNamesAndIdsStatement{ + "SELECT projectPartName, projectPartId FROM projectParts", database}; }; } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/projectpartsstorageinterface.h b/src/libs/clangsupport/projectpartsstorageinterface.h index 2d0675e6579..ec1ce65dd06 100644 --- a/src/libs/clangsupport/projectpartsstorageinterface.h +++ b/src/libs/clangsupport/projectpartsstorageinterface.h @@ -25,7 +25,8 @@ #pragma once -#include +#include "projectpartcontainer.h" +#include "projectpartstoragestructs.h" #include #include @@ -46,8 +47,10 @@ public: virtual ProjectPartContainers fetchProjectParts() const = 0; virtual ProjectPartContainers fetchProjectParts(const ProjectPartIds &projectPartIds) const = 0; + virtual ProjectPartId fetchProjectPartIdUnguarded(Utils::SmallStringView projectPartName) const = 0; virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) const = 0; virtual Utils::PathString fetchProjectPartName(ProjectPartId projectPartId) const = 0; + virtual Internal::ProjectPartNameIds fetchAllProjectPartNamesAndIds() const = 0; virtual void updateProjectPart(ProjectPartId projectPartId, const Utils::SmallStringVector &commandLineArguments, const CompilerMacros &compilerMacros, diff --git a/src/plugins/clangpchmanager/projectupdater.cpp b/src/plugins/clangpchmanager/projectupdater.cpp index 5bb1cf5ccda..e006357e0c5 100644 --- a/src/plugins/clangpchmanager/projectupdater.cpp +++ b/src/plugins/clangpchmanager/projectupdater.cpp @@ -46,8 +46,11 @@ #include #include +#include + #include #include +#include namespace ClangPchManager { @@ -68,6 +71,7 @@ void ProjectUpdater::updateProjectParts(const std::vector( @@ -347,10 +351,10 @@ ClangBackEnd::ProjectPartContainer ProjectUpdater::toProjectPartContainer( auto includeSearchPaths = createIncludeSearchPaths(*projectPart); - const QByteArray projectPartName = projectPart->id().toUtf8(); - - ClangBackEnd::ProjectPartId projectPartId = m_projectPartsStorage.fetchProjectPartId( - projectPartName); + ClangBackEnd::ProjectPartId projectPartId = m_projectPartIdCache.stringId( + Utils::PathString{projectPart->id()}, [&](Utils::SmallStringView projectPartName) { + return m_projectPartsStorage.fetchProjectPartId(projectPartName); + }); ClangIndexingProjectSettings *settings = m_settingsManager.settings(projectPart->project); @@ -415,36 +419,31 @@ ClangBackEnd::FilePaths ProjectUpdater::createExcludedPaths( QString ProjectUpdater::fetchProjectPartName(ClangBackEnd::ProjectPartId projectPartId) const { - return m_projectPartsStorage.fetchProjectPartName(projectPartId).toQString(); + return QString(m_projectPartIdCache.string(projectPartId.projectPathId, + [&](ClangBackEnd::ProjectPartId projectPartId) { + return m_projectPartsStorage.fetchProjectPartName( + projectPartId); + })); } ClangBackEnd::ProjectPartIds ProjectUpdater::toProjectPartIds( - const QStringList &projectPartNames) const + const QStringList &projectPartNamesAsQString) const { ClangBackEnd::ProjectPartIds projectPartIds; projectPartIds.reserve(projectPartIds.size()); - std::transform(projectPartNames.begin(), - projectPartNames.end(), - std::back_inserter(projectPartIds), - [&](const QString &projectPartName) { - return m_projectPartsStorage.fetchProjectPartId( - Utils::SmallString{projectPartName}); - }); + auto projectPartNames = Utils::transform>( + projectPartNamesAsQString, [&](const QString &projectPartName) { return projectPartName; }); - return projectPartIds; + return m_projectPartIdCache.stringIds(projectPartNames, [&](Utils::SmallStringView projectPartName) { + return m_projectPartsStorage.fetchProjectPartId(projectPartName); + }); } void ProjectUpdater::addProjectFilesToFilePathCache(const std::vector &projectParts) { - std::size_t fileCount = std::accumulate(projectParts.begin(), - projectParts.end(), - std::size_t(0), - [](std::size_t value, CppTools::ProjectPart *projectPart) { - return value + std::size_t(projectPart->files.size()); - }); ClangBackEnd::FilePaths filePaths; - filePaths.reserve(fileCount); + filePaths.reserve(10000); for (CppTools::ProjectPart *projectPart : projectParts) { for (const CppTools::ProjectFile &file : projectPart->files) @@ -455,4 +454,28 @@ void ProjectUpdater::addProjectFilesToFilePathCache(const std::vector &projectParts) +{ + std::unique_ptr transaction; + + auto projectPartNames = Utils::transform>( + projectParts, [](CppTools::ProjectPart *projectPart) { return projectPart->id(); }); + + auto projectPartNameViews = Utils::transform>( + projectPartNames, + [](const Utils::PathString &projectPartName) { return projectPartName.toStringView(); }); + + m_projectPartIdCache + .addStrings(std::move(projectPartNameViews), [&](Utils::SmallStringView projectPartName) { + if (!transaction) + transaction = std::make_unique( + m_projectPartsStorage.transactionBackend()); + return m_projectPartsStorage.fetchProjectPartIdUnguarded(projectPartName); + }); + + if (transaction) + transaction->commit(); + +} // namespace ClangPchManager + } // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/projectupdater.h b/src/plugins/clangpchmanager/projectupdater.h index c3f793dc2fd..16d662004fb 100644 --- a/src/plugins/clangpchmanager/projectupdater.h +++ b/src/plugins/clangpchmanager/projectupdater.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include @@ -66,6 +68,14 @@ class ClangIndexingProjectSettings; class CLANGPCHMANAGER_EXPORT ProjectUpdater { + using StringCache = ClangBackEnd::StringCache; + public: struct SystemAndProjectIncludeSearchPaths { @@ -77,11 +87,13 @@ public: ClangBackEnd::FilePathCachingInterface &filePathCache, ClangBackEnd::ProjectPartsStorageInterface &projectPartsStorage, ClangIndexingSettingsManager &settingsManager) - : m_server(server) - , m_filePathCache(filePathCache) + : m_filePathCache(filePathCache) + , m_server(server) , m_projectPartsStorage(projectPartsStorage) , m_settingsManager(settingsManager) - {} + { + m_projectPartIdCache.populate(m_projectPartsStorage.fetchAllProjectPartNamesAndIds()); + } void updateProjectParts(const std::vector &projectParts, Utils::SmallStringVector &&toolChainArguments); @@ -104,8 +116,8 @@ public: void addToHeaderAndSources(HeaderAndSources &headerAndSources, const CppTools::ProjectFile &projectFile) const; static QStringList toolChainArguments(CppTools::ProjectPart *projectPart); - ClangBackEnd::CompilerMacros createCompilerMacros(const ProjectExplorer::Macros &projectMacros, - Utils::NameValueItems &&settingsMacros) const; + static ClangBackEnd::CompilerMacros createCompilerMacros(const ProjectExplorer::Macros &projectMacros, + Utils::NameValueItems &&settingsMacros); static SystemAndProjectIncludeSearchPaths createIncludeSearchPaths( const CppTools::ProjectPart &projectPart); static ClangBackEnd::FilePaths createExcludedPaths( @@ -115,16 +127,19 @@ public: ClangBackEnd::ProjectPartIds toProjectPartIds(const QStringList &projectPartNames) const; -private: void addProjectFilesToFilePathCache(const std::vector &projectParts); + void fetchProjectPartIds(const std::vector &projectParts); + +protected: + ClangBackEnd::FilePathCachingInterface &m_filePathCache; private: ClangBackEnd::GeneratedFiles m_generatedFiles; ClangBackEnd::FilePaths m_excludedPaths; ClangBackEnd::ProjectManagementServerInterface &m_server; - ClangBackEnd::FilePathCachingInterface &m_filePathCache; ClangBackEnd::ProjectPartsStorageInterface &m_projectPartsStorage; ClangIndexingSettingsManager &m_settingsManager; + mutable StringCache m_projectPartIdCache; }; } // namespace ClangPchManager diff --git a/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp b/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp index 5331e2ef052..9a3b1498cc2 100644 --- a/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp +++ b/src/plugins/clangpchmanager/qtcreatorprojectupdater.cpp @@ -29,6 +29,8 @@ #include +#include + namespace ClangPchManager { namespace Internal { @@ -38,16 +40,21 @@ CppTools::CppModelManager *cppModelManager() return CppTools::CppModelManager::instance(); } -std::vector createGeneratedFiles() +std::vector createGeneratedFiles( + ClangBackEnd::FilePathCachingInterface &filePathCache) { auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports(); std::vector generatedFiles; generatedFiles.reserve(std::size_t(abstractEditors.size())); - auto toFileContainer = [] (const CppTools::AbstractEditorSupport *abstractEditor) { - return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()), - Utils::SmallString::fromQByteArray(abstractEditor->contents()), - {}); + auto toFileContainer = [&](const CppTools::AbstractEditorSupport *abstractEditor) { + ClangBackEnd::FilePath filePath(abstractEditor->fileName()); + ClangBackEnd::FilePathId filePathId = filePathCache.filePathId(filePath); + return ClangBackEnd::V2::FileContainer(std::move(filePath), + filePathId, + Utils::SmallString::fromQByteArray( + abstractEditor->contents()), + {}); }; std::transform(abstractEditors.begin(), diff --git a/src/plugins/clangpchmanager/qtcreatorprojectupdater.h b/src/plugins/clangpchmanager/qtcreatorprojectupdater.h index 143ffea655f..1cada833e7d 100644 --- a/src/plugins/clangpchmanager/qtcreatorprojectupdater.h +++ b/src/plugins/clangpchmanager/qtcreatorprojectupdater.h @@ -32,6 +32,8 @@ #include +#include + #include namespace ProjectExplorer { @@ -46,7 +48,8 @@ namespace ClangPchManager { namespace Internal { CLANGPCHMANAGER_EXPORT CppTools::CppModelManager *cppModelManager(); -CLANGPCHMANAGER_EXPORT std::vector createGeneratedFiles(); +CLANGPCHMANAGER_EXPORT std::vector createGeneratedFiles( + ClangBackEnd::FilePathCachingInterface &filePathCache); CLANGPCHMANAGER_EXPORT std::vector createProjectParts(ProjectExplorer::Project *project); } @@ -83,9 +86,13 @@ public: ProjectUpdaterType::removeProjectParts(projectPartIds); } - void abstractEditorUpdated(const QString &filePath, const QByteArray &contents) + void abstractEditorUpdated(const QString &qFilePath, const QByteArray &contents) { - ProjectUpdaterType::updateGeneratedFiles({{ClangBackEnd::FilePath{filePath}, contents}}); + ClangBackEnd::FilePath filePath{qFilePath}; + ClangBackEnd::FilePathId filePathId = ProjectUpdaterType::m_filePathCache.filePathId( + filePath); + + ProjectUpdaterType::updateGeneratedFiles({{std::move(filePath), filePathId, contents}}); } void abstractEditorRemoved(const QString &filePath) @@ -98,6 +105,14 @@ protected: const Utils::FilePath &, const Utils::FilePathList &targets) override { + auto filePaths = Utils::transform(targets, + [](const Utils::FilePath &filePath) { + return ClangBackEnd::FilePath{ + filePath.toString()}; + }); + + ProjectUpdater::m_filePathCache.addFilePaths(filePaths); + for (const Utils::FilePath &target : targets) abstractEditorUpdated(target.toString(), {}); } @@ -105,7 +120,8 @@ protected: private: void connectToCppModelManager() { - ProjectUpdaterType::updateGeneratedFiles(Internal::createGeneratedFiles()); + ProjectUpdaterType::updateGeneratedFiles( + Internal::createGeneratedFiles(ProjectUpdaterType::m_filePathCache)); QObject::connect(Internal::cppModelManager(), &CppTools::CppModelManager::projectPartsUpdated, diff --git a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp index 5e6246ad5e4..f60aaff6e8c 100644 --- a/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp +++ b/src/plugins/clangrefactoring/clangqueryprojectsfindfilter.cpp @@ -82,10 +82,9 @@ void ClangQueryProjectsFindFilter::requestSourceRangesAndDiagnostics(const QStri { const QString filePath = temporaryFile.fileName(); - ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message(queryText, - {ClangBackEnd::FilePath(filePath), - exampleContent, - {"cc", "-std=c++1z", toNative(filePath)}}); + ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message( + queryText, + {ClangBackEnd::FilePath(filePath), 1, exampleContent, {"cc", "-std=c++1z", toNative(filePath)}}); m_server.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(message)); } @@ -204,10 +203,9 @@ void appendSource(std::vector &sources, if (!unsavedContentContains(sourceFilePath, unsavedContent) && !isCHeader(projectFile.kind)) { sources.emplace_back(ClangBackEnd::FilePath(projectFile.path), + -1, "", - createCommandLine(projectPart.data(), - projectFile.path, - projectFile.kind)); + createCommandLine(projectPart.data(), projectFile.path, projectFile.kind)); } } diff --git a/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.cpp b/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.cpp index 05c378b196d..e3dc7ee4e87 100644 --- a/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.cpp +++ b/src/plugins/clangrefactoring/qtcreatorclangqueryfindfilter.cpp @@ -108,10 +108,12 @@ std::vector createUnsavedContents() std::vector unsavedContents; unsavedContents.reserve(std::size_t(abstractEditors.size())); - auto toFileContainer = [] (const CppTools::AbstractEditorSupport *abstractEditor) { - return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()), - Utils::SmallString::fromQByteArray(abstractEditor->contents()), - {}); + auto toFileContainer = [](const CppTools::AbstractEditorSupport *abstractEditor) { + return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()), + -1, + Utils::SmallString::fromQByteArray( + abstractEditor->contents()), + {}); }; std::transform(abstractEditors.begin(), diff --git a/src/plugins/clangrefactoring/qtcreatorrefactoringprojectupdater.cpp b/src/plugins/clangrefactoring/qtcreatorrefactoringprojectupdater.cpp index 2d71b7b9fb6..415186d5558 100644 --- a/src/plugins/clangrefactoring/qtcreatorrefactoringprojectupdater.cpp +++ b/src/plugins/clangrefactoring/qtcreatorrefactoringprojectupdater.cpp @@ -37,16 +37,21 @@ CppTools::CppModelManager *cppModelManager() return CppTools::CppModelManager::instance(); } -std::vector createGeneratedFiles() +std::vector createGeneratedFiles( + ClangBackEnd::FilePathCachingInterface &filePathCache) { auto abstractEditors = CppTools::CppModelManager::instance()->abstractEditorSupports(); std::vector generatedFiles; generatedFiles.reserve(std::size_t(abstractEditors.size())); - auto toFileContainer = [] (const CppTools::AbstractEditorSupport *abstractEditor) { - return ClangBackEnd::V2::FileContainer(ClangBackEnd::FilePath(abstractEditor->fileName()), - Utils::SmallString::fromQByteArray(abstractEditor->contents()), - {}); + auto toFileContainer = [&](const CppTools::AbstractEditorSupport *abstractEditor) { + ClangBackEnd::FilePath filePath{abstractEditor->fileName()}; + ClangBackEnd::FilePathId filePathId = filePathCache.filePathId(filePath); + return ClangBackEnd::V2::FileContainer(std::move(filePath), + filePathId, + Utils::SmallString::fromQByteArray( + abstractEditor->contents()), + {}); }; std::transform(abstractEditors.begin(), @@ -76,9 +81,12 @@ QtCreatorRefactoringProjectUpdater::QtCreatorRefactoringProjectUpdater( connectToCppModelManager(); } -void QtCreatorRefactoringProjectUpdater::abstractEditorUpdated(const QString &filePath, const QByteArray &contents) +void QtCreatorRefactoringProjectUpdater::abstractEditorUpdated(const QString &qFilePath, + const QByteArray &contents) { - RefactoringProjectUpdater::updateGeneratedFiles({{ClangBackEnd::FilePath{filePath}, contents}}); + ClangBackEnd::FilePath filePath{qFilePath}; + ClangBackEnd::FilePathId filePathId = m_filePathCache.filePathId(filePath); + RefactoringProjectUpdater::updateGeneratedFiles({{std::move(filePath), filePathId, contents}}); } void QtCreatorRefactoringProjectUpdater::abstractEditorRemoved(const QString &filePath) @@ -88,7 +96,7 @@ void QtCreatorRefactoringProjectUpdater::abstractEditorRemoved(const QString &fi void QtCreatorRefactoringProjectUpdater::connectToCppModelManager() { - RefactoringProjectUpdater::updateGeneratedFiles(createGeneratedFiles()); + RefactoringProjectUpdater::updateGeneratedFiles(createGeneratedFiles(m_filePathCache)); QObject::connect(cppModelManager(), &CppTools::CppModelManager::abstractEditorSupportContentsUpdated, diff --git a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp index 1dd3f9acbe0..7a871bb0337 100644 --- a/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp +++ b/src/tools/clangpchmanagerbackend/clangpchmanagerbackendmain.cpp @@ -232,9 +232,8 @@ struct Data // because we have a cycle dependency pchTaskGenerator, projectParts, generatedFiles, - buildDependencyStorage/*, - buildDependencyProvider, - filePathCache*/}; + buildDependencyStorage, + filePathCache}; TaskScheduler systemTaskScheduler{pchCreatorManager, pchTaskQueue, pchCreationProgressCounter, diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp index ee3d3d02aab..fa69cd56ca7 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.cpp @@ -41,6 +41,7 @@ #include #include +#include #include @@ -50,12 +51,14 @@ PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher, PchTaskGeneratorInterface &pchTaskGenerator, ProjectPartsManagerInterface &projectParts, GeneratedFilesInterface &generatedFiles, - BuildDependenciesStorageInterface &buildDependenciesStorage) + BuildDependenciesStorageInterface &buildDependenciesStorage, + FilePathCachingInterface &filePathCache) : m_fileSystemWatcher(fileSystemWatcher) , m_pchTaskGenerator(pchTaskGenerator) , m_projectPartsManager(projectParts) , m_generatedFiles(generatedFiles) , m_buildDependenciesStorage(buildDependenciesStorage) + , m_filePathCache(filePathCache) { m_fileSystemWatcher.setNotifier(this); } @@ -73,10 +76,43 @@ ProjectPartIds toProjectPartIds(const ProjectPartContainers &projectParts) }); } +FilePaths gatherPathsInIncludePaths(const ProjectPartContainers &projectParts) +{ + FilePaths filePaths; + + for (const ProjectPartContainer &projectPart : projectParts) { + for (const IncludeSearchPath &searchPath : projectPart.projectIncludeSearchPaths) { + QDirIterator directoryIterator(QString{searchPath.path}, + {"*.h", "*.hpp"}, + QDir::Files, + QDirIterator::FollowSymlinks + | QDirIterator::Subdirectories); + while (directoryIterator.hasNext()) { + filePaths.emplace_back(directoryIterator.next()); + } + } + for (const IncludeSearchPath &searchPath : projectPart.systemIncludeSearchPaths) { + QDirIterator directoryIterator(QString{searchPath.path}, + {"*.h", "*.hpp"}, + QDir::Files, + QDirIterator::FollowSymlinks); + while (directoryIterator.hasNext()) { + filePaths.emplace_back(directoryIterator.next()); + } + } + } + + return filePaths; +} + } // namespace void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message) { + m_filePathCache.populateIfEmpty(); + + m_filePathCache.addFilePaths(gatherPathsInIncludePaths(message.projectsParts)); + m_toolChainsArgumentsCache.update(message.projectsParts, message.toolChainArguments); auto upToDateProjectParts = m_projectPartsManager.update(message.takeProjectsParts()); diff --git a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h index c8e5be4de57..7b1187d5f4b 100644 --- a/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h +++ b/src/tools/clangpchmanagerbackend/source/pchmanagerserver.h @@ -40,6 +40,7 @@ namespace ClangBackEnd { class SourceRangesAndDiagnosticsForQueryMessage; class PchTaskGeneratorInterface; class BuildDependenciesStorageInterface; +class FilePathCachingInterface; class PchManagerServer : public PchManagerServerInterface, public ClangPathWatcherNotifier, @@ -51,7 +52,8 @@ public: PchTaskGeneratorInterface &pchTaskGenerator, ProjectPartsManagerInterface &projectParts, GeneratedFilesInterface &generatedFiles, - BuildDependenciesStorageInterface &buildDependenciesStorage); + BuildDependenciesStorageInterface &buildDependenciesStorage, + FilePathCachingInterface &filePathCache); void end() override; void updateProjectParts(UpdateProjectPartsMessage &&message) override; @@ -76,6 +78,7 @@ private: GeneratedFilesInterface &m_generatedFiles; BuildDependenciesStorageInterface &m_buildDependenciesStorage; ToolChainsArgumentsCache m_toolChainsArgumentsCache; + FilePathCachingInterface &m_filePathCache; }; } // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp index 548dd373ac1..5e8f6fe0ef4 100644 --- a/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp +++ b/src/tools/clangpchmanagerbackend/source/projectpartsmanager.cpp @@ -56,27 +56,6 @@ namespace { enum class Change { System, Project, No }; -Change changedSourceType(const SourceEntries &sources) -{ - Change change = Change::No; - for (SourceEntry sourceEntry : sources) { - switch (sourceEntry.sourceType) { - case SourceType::SystemInclude: - case SourceType::TopSystemInclude: - return Change::System; - case SourceType::ProjectInclude: - case SourceType::TopProjectInclude: - change = Change::Project; - break; - case SourceType::Source: - case SourceType::UserInclude: - break; - } - } - - return change; -} - Change changedSourceType(SourceEntry sourceEntry, Change oldChange) { switch (sourceEntry.sourceType) { @@ -109,16 +88,6 @@ FilePathIds existingSources(const FilePathIds &sources, const FilePathIds &gener return existingSources; } -FilePathIds toFilePathIds(const V2::FileContainers &fileContainers, - FilePathCachingInterface &filePathCache) -{ - auto filePaths = Utils::transform>( - fileContainers, - [](const V2::FileContainer &container) { return FilePathView(container.filePath); }); - - return filePathCache.filePathIds(filePaths); -} - } // namespace ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts) @@ -175,7 +144,7 @@ ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDep auto systemSplit = updateSystemProjectParts.end(); - FilePathIds generatedFiles = toFilePathIds(m_generatedFiles.fileContainers(), m_filePathCache); + FilePathIds generatedFiles = m_generatedFiles.filePathIds(); std::vector watchedIdPaths; watchedIdPaths.reserve(upToDateProjectParts.size() * 4); diff --git a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp index 2f79ae31cc8..b86a93ad326 100644 --- a/src/tools/clangrefactoringbackend/source/refactoringserver.cpp +++ b/src/tools/clangrefactoringbackend/source/refactoringserver.cpp @@ -81,6 +81,7 @@ void RefactoringServer::requestSourceRangesForQueryMessage(RequestSourceRangesFo void RefactoringServer::updateProjectParts(UpdateProjectPartsMessage &&message) { + m_filePathCache.populateIfEmpty(); m_symbolIndexing.updateProjectParts(message.takeProjectsParts()); } diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h index 1f15f2ffaa0..aa74fb833b7 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h @@ -57,7 +57,7 @@ public: , m_database(database) {} - void addOrUpdateTasks(std::vector &&tasks) + void addOrUpdateTasks(std::vector &&tasks) override { auto merge = [] (SymbolIndexerTask &&first, SymbolIndexerTask &&second) { first.callable = std::move(second.callable); @@ -71,7 +71,7 @@ public: m_progressCounter.addTotal(int(m_tasks.size() - oldSize)); } - void removeTasks(const std::vector &projectPartIds) + void removeTasks(const ProjectPartIds &projectPartIds) override { auto shouldBeRemoved = [&] (const SymbolIndexerTask& task) { return std::binary_search(projectPartIds.begin(), projectPartIds.end(), task.projectPartId); @@ -91,7 +91,7 @@ public: return m_tasks; } - void processEntries() + void processEntries() override { auto slotUsage = m_symbolIndexerScheduler.slotUsage(); uint taskCount = slotUsage.free; diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueueinterface.h b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueueinterface.h index dfcc78bd235..3c5bc3479f9 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueueinterface.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueueinterface.h @@ -27,6 +27,8 @@ #include +#include + #include namespace ClangBackEnd { @@ -38,8 +40,8 @@ class SymbolIndexerTaskQueueInterface : public QueueInterface public: virtual void addOrUpdateTasks(std::vector &&tasks) = 0 /* [[expects: std::is_sorted(tasks)]] */; - virtual void removeTasks(const std::vector &projectPartIds) = 0 - /* [[expects: std::is_sorted(projectPartIds)]] */; + virtual void removeTasks(const ProjectPartIds &projectPartIds) = 0 + /* [[expects: std::is_sorted(projectPartIds)]] */; protected: ~SymbolIndexerTaskQueueInterface() = default; diff --git a/tests/unit/unittest/builddependencycollector-test.cpp b/tests/unit/unittest/builddependencycollector-test.cpp index 352a60f1def..7bfe6de4cca 100644 --- a/tests/unit/unittest/builddependencycollector-test.cpp +++ b/tests/unit/unittest/builddependencycollector-test.cpp @@ -106,6 +106,7 @@ protected: collector.addUnsavedFiles( {{{TESTDATA_DIR, "BuildDependencyCollector/project/generated_file.h"}, + id(TESTDATA_DIR "/BuildDependencyCollector/project/generated_file.h"), "#pragma once", {}}}); @@ -741,6 +742,7 @@ TEST_F(BuildDependencyCollector, GeneratedFile) { generatedFiles.update( {{TESTDATA_DIR "/builddependencycollector/project/generated/generated_file.h", + id(TESTDATA_DIR "/builddependencycollector/project/generated/generated_file.h"), "#pragma once"}}); emptyCollector.addFile(id(TESTDATA_DIR "/builddependencycollector/project/main6.cpp"), {"cc", @@ -754,9 +756,9 @@ TEST_F(BuildDependencyCollector, GeneratedFile) emptyCollector.collect(); - ASSERT_THAT( - emptyCollector.sourceEntries(), - ElementsAre(HasSource(id(TESTDATA_DIR "/builddependencycollector/project/main6.cpp"), + ASSERT_THAT(emptyCollector.sourceEntries(), + UnorderedElementsAre( + HasSource(id(TESTDATA_DIR "/builddependencycollector/project/main6.cpp"), SourceType::Source), HasSource(id(TESTDATA_DIR "/builddependencycollector/project/generated/generated_file.h"), @@ -783,8 +785,9 @@ TEST_F(BuildDependencyCollector, Create) { using ClangBackEnd::IncludeSearchPathType; ClangBackEnd::BuildDependencyCollector collector{filePathCache, generatedFiles, environment}; - generatedFiles.update( - {{TESTDATA_DIR "/builddependencycollector/project/generated_file.h", "#pragma once"}}); + generatedFiles.update({{TESTDATA_DIR "/builddependencycollector/project/generated_file.h", + id(TESTDATA_DIR "/builddependencycollector/project/generated_file.h"), + "#pragma once"}}); ClangBackEnd::ProjectPartContainer projectPart{ 1, {}, diff --git a/tests/unit/unittest/clangquery-test.cpp b/tests/unit/unittest/clangquery-test.cpp index 77a049210b7..f17d4166138 100644 --- a/tests/unit/unittest/clangquery-test.cpp +++ b/tests/unit/unittest/clangquery-test.cpp @@ -40,6 +40,7 @@ #include using ClangBackEnd::ClangQuery; +using ClangBackEnd::FilePath; using ClangBackEnd::FilePathCaching; using ClangBackEnd::RefactoringDatabaseInitializer; @@ -98,7 +99,11 @@ TEST_F(ClangQuerySlowTest, SourceRangeInUnsavedFileDeclarationRange) "#include \"unsaved.h\"", {"cc", "-std=c++14"}); query.setQuery("functionDecl()"); - ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "unsaved.h"}, "void unsaved();", {}}; + ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR, "unsaved.h"}, + filePathCache.filePathId( + FilePath{TESTDATA_DIR, "unsaved.h"}), + "void unsaved();", + {}}; query.addUnsavedFiles({unsavedFile}); query.findLocations(); @@ -125,6 +130,8 @@ TEST_F(ClangQuerySlowTest, DISABLED_SourceRangeInUnsavedFileDeclarationRangeOver query.addFile({TESTDATA_DIR "/query_simplefunction.cpp"}, "void f() {}", {"cc", "-std=c++14"}); query.setQuery("functionDecl()"); ClangBackEnd::V2::FileContainer unsavedFile{{TESTDATA_DIR "/query_simplefunction.cpp"}, + filePathCache.filePathId( + FilePath{TESTDATA_DIR, "query_simplefunction.cpp"}), "void unsaved();", {}}; query.addUnsavedFiles({unsavedFile}); diff --git a/tests/unit/unittest/clangquerygatherer-test.cpp b/tests/unit/unittest/clangquerygatherer-test.cpp index 3b5f9239fed..c301af4ad05 100644 --- a/tests/unit/unittest/clangquerygatherer-test.cpp +++ b/tests/unit/unittest/clangquerygatherer-test.cpp @@ -59,10 +59,10 @@ using testing::SizeIs; using testing::UnorderedElementsAre; using testing::_; -using ClangBackEnd::V2::FileContainer; +using ClangBackEnd::FilePath; +using ClangBackEnd::SourceRangesContainer; using ClangBackEnd::SourceRangesForQueryMessage; -using ClangBackEnd::SourceRangesContainer; -using ClangBackEnd::SourceRangesContainer; +using ClangBackEnd::V2::FileContainer; MATCHER_P2(Contains, line, column, std::string(negation ? "isn't " : "is ") @@ -86,22 +86,20 @@ protected: ClangBackEnd::FilePathCaching filePathCache{database}; Utils::SmallString sourceContent{"#include \"query_simplefunction.h\"\nvoid f() {}"}; FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, + filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.cpp"}), sourceContent.clone(), - {"cc", - "-I", - TESTDATA_DIR}}; + {"cc", "-I", TESTDATA_DIR}}; FileContainer source2{{TESTDATA_DIR, "query_simplefunction2.cpp"}, + filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction2.cpp"}), {}, - {"cc", - "-I", - TESTDATA_DIR}}; + {"cc", "-I", TESTDATA_DIR}}; FileContainer source3{{TESTDATA_DIR, "query_simplefunction3.cpp"}, + filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction3.cpp"}), {}, - {"cc", - "-I", - TESTDATA_DIR}}; + {"cc", "-I", TESTDATA_DIR}}; Utils::SmallString unsavedContent{"void f();"}; FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"}, + filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.h"}), unsavedContent.clone(), {}}; Utils::SmallString query{"functionDecl()"}; diff --git a/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp b/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp index 39819809029..65169cb745f 100644 --- a/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp +++ b/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp @@ -122,9 +122,7 @@ protected: QString unsavedDocumentContent{"void f();"}; std::vector commandLines; std::vector projectsParts; - ClangBackEnd::V2::FileContainer unsavedContent{{"/path/to", "unsaved.cpp"}, - "void f();", - {}}; + ClangBackEnd::V2::FileContainer unsavedContent{{"/path/to", "unsaved.cpp"}, 1, "void f();", {}}; ProjectExplorer::Project project; }; @@ -186,17 +184,12 @@ TEST_F(ClangQueryProjectFindFilter, FindAllIsSettingExprectedResultCountInTheRef TEST_F(ClangQueryProjectFindFilter, FindAllIsCallingRequestSourceRangesAndDiagnosticsForQueryMessage) { - ClangBackEnd::RequestSourceRangesForQueryMessage message(findDeclQueryText, - {{{"/path/to", "file1.h"}, - "", - commandLines[0].clone()}, - {{"/path/to", "file1.cpp"}, - "", - commandLines[1].clone()}, - {{"/path/to", "file2.cpp"}, - "", - commandLines[2].clone()}}, - {unsavedContent.clone()}); + ClangBackEnd::RequestSourceRangesForQueryMessage message( + findDeclQueryText, + {{{"/path/to", "file1.h"}, 1, "", commandLines[0].clone()}, + {{"/path/to", "file1.cpp"}, 2, "", commandLines[1].clone()}, + {{"/path/to", "file2.cpp"}, 3, "", commandLines[2].clone()}}, + {unsavedContent.clone()}); EXPECT_CALL(mockRefactoringServer, requestSourceRangesForQueryMessage(message)); diff --git a/tests/unit/unittest/filepathcache-test.cpp b/tests/unit/unittest/filepathcache-test.cpp index 789eb664511..95557961161 100644 --- a/tests/unit/unittest/filepathcache-test.cpp +++ b/tests/unit/unittest/filepathcache-test.cpp @@ -79,6 +79,7 @@ protected: NiceMock mockStorage{mockDatabase}; Cache cache{mockStorage}; NiceMock mockStorageFilled{mockDatabase}; + Cache cacheNotFilled{mockStorageFilled}; }; TEST_F(FilePathCache, FilePathIdWithOutAnyEntryCallDirectoryId) @@ -439,4 +440,51 @@ TEST_F(FilePathCache, UseTransactionIfAddingFilesOnlyInAddFilePathsCalls) cacheFilled.addFilePaths(FilePathViews{"/path/to/file.h"}); } + +TEST_F(FilePathCache, GetFileIdInAfterPopulateIfEmpty) +{ + cacheNotFilled.populateIfEmpty(); + + auto id = cacheNotFilled.filePathId("/path2/to/file.cpp"); + + ASSERT_THAT(id, Eq(72)); +} + +TEST_F(FilePathCache, DontPopulateIfNotEmpty) +{ + cacheNotFilled.filePathId("/path/to/file.cpp"); + cacheNotFilled.populateIfEmpty(); + + auto id = cacheNotFilled.filePathId("/path2/to/file.cpp"); + + ASSERT_FALSE(id.isValid()); +} + +TEST_F(FilePathCache, GetDirectoryIdAfterPopulateIfEmpty) +{ + cacheNotFilled.populateIfEmpty(); + + auto id = cacheNotFilled.directoryPathId(42); + + ASSERT_THAT(id, Eq(5)); +} + +TEST_F(FilePathCache, GetDirectoryPathAfterPopulateIfEmpty) +{ + cacheNotFilled.populateIfEmpty(); + + auto path = cacheNotFilled.directoryPath(5); + + ASSERT_THAT(path, Eq("/path/to")); +} + +TEST_F(FilePathCache, GetFilePathAfterPopulateIfEmptye) +{ + cacheNotFilled.populateIfEmpty(); + + auto path = cacheNotFilled.filePath(42); + + ASSERT_THAT(path, Eq("/path/to/file.cpp")); +} + } // namespace diff --git a/tests/unit/unittest/generatedfiles-test.cpp b/tests/unit/unittest/generatedfiles-test.cpp index 9db9c4b0aee..8e5a34ffd71 100644 --- a/tests/unit/unittest/generatedfiles-test.cpp +++ b/tests/unit/unittest/generatedfiles-test.cpp @@ -35,12 +35,12 @@ using ClangBackEnd::V2::FileContainers; class GeneratedFiles : public testing::Test { protected: - FileContainer file1{"/file1", "content1"}; - FileContainer file1b{"/file1", "content1b"}; - FileContainer file2{"/file2", "content2"}; - FileContainer file2b{"/file2", "content2b"}; - FileContainer file3{"/file3", "content3"}; - FileContainer file4{"/file4", "content4"}; + FileContainer file1{"/file1", 1, "content1"}; + FileContainer file1b{"/file1", 1, "content1b"}; + FileContainer file2{"/file2", 2, "content2"}; + FileContainer file2b{"/file2", 2, "content2b"}; + FileContainer file3{"/file3", 3, "content3"}; + FileContainer file4{"/file4", 4, "content4"}; ClangBackEnd::GeneratedFiles generatedFiles; }; @@ -76,7 +76,7 @@ TEST_F(GeneratedFiles, IsValidForNoGeneratedFiles) TEST_F(GeneratedFiles, IsNotValidIfFilesWithNotContentExists) { - generatedFiles.update({{"/file2", ""}}); + generatedFiles.update({{"/file2", 2, ""}}); ASSERT_FALSE(generatedFiles.isValid()); } @@ -86,4 +86,15 @@ TEST_F(GeneratedFiles, IsValidIfAllFilesHasContent) generatedFiles.update({file1, file2, file3, file4}); ASSERT_TRUE(generatedFiles.isValid()); -}} +} + +TEST_F(GeneratedFiles, GetFilePathIds) +{ + generatedFiles.update({file3, file2, file1, file4}); + + auto ids = generatedFiles.filePathIds(); + + ASSERT_THAT(ids, ElementsAre(1, 2, 3, 4)); +} + +} // namespace diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index b533186739d..624288ee98d 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -106,7 +106,7 @@ void PrintTo(Utils::SmallStringView text, ::std::ostream *os); void PrintTo(const Utils::SmallString &text, ::std::ostream *os); void PrintTo(const Utils::PathString &text, ::std::ostream *os); -} // namespace ProjectExplorer +} // namespace Utils namespace ClangBackEnd { class SourceLocationEntry; diff --git a/tests/unit/unittest/mockfilepathcaching.h b/tests/unit/unittest/mockfilepathcaching.h index bec249a5a53..155aa491c97 100644 --- a/tests/unit/unittest/mockfilepathcaching.h +++ b/tests/unit/unittest/mockfilepathcaching.h @@ -43,4 +43,5 @@ public: MOCK_CONST_METHOD1(directoryPathId, ClangBackEnd::DirectoryPathId(ClangBackEnd::FilePathId filePathId)); MOCK_METHOD1(addFilePaths, void(const ClangBackEnd::FilePaths &filePaths)); + MOCK_METHOD0(populateIfEmpty, void()); }; diff --git a/tests/unit/unittest/mockgeneratedfiles.h b/tests/unit/unittest/mockgeneratedfiles.h index 75b182355c2..481747c27ff 100644 --- a/tests/unit/unittest/mockgeneratedfiles.h +++ b/tests/unit/unittest/mockgeneratedfiles.h @@ -38,6 +38,7 @@ public: void (const ClangBackEnd::FilePaths &filePaths)); MOCK_CONST_METHOD0(fileContainers, const ClangBackEnd::V2::FileContainers &()); + MOCK_CONST_METHOD0(filePathIds, ClangBackEnd::FilePathIds()); MOCK_CONST_METHOD0(isValid, bool()); void update(ClangBackEnd::V2::FileContainers &&fileContainers) diff --git a/tests/unit/unittest/mockprojectpartsstorage.h b/tests/unit/unittest/mockprojectpartsstorage.h index e8dcbc94b2e..cdca4ef78e3 100644 --- a/tests/unit/unittest/mockprojectpartsstorage.h +++ b/tests/unit/unittest/mockprojectpartsstorage.h @@ -36,8 +36,11 @@ public: MOCK_CONST_METHOD1( fetchProjectParts, ClangBackEnd::ProjectPartContainers(const ClangBackEnd::ProjectPartIds &projectPartIds)); + MOCK_CONST_METHOD0(fetchAllProjectPartNamesAndIds, ClangBackEnd::Internal::ProjectPartNameIds()); MOCK_CONST_METHOD1(fetchProjectPartId, ClangBackEnd::ProjectPartId(Utils::SmallStringView projectPartName)); + MOCK_CONST_METHOD1(fetchProjectPartIdUnguarded, + ClangBackEnd::ProjectPartId(Utils::SmallStringView projectPartName)); MOCK_CONST_METHOD1(fetchProjectPartName, Utils::PathString(ClangBackEnd::ProjectPartId projectPartId)); MOCK_METHOD8(updateProjectPart, diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp index 9a949e4b0a9..0a63f3c284e 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.cpp +++ b/tests/unit/unittest/mocksqlitereadstatement.cpp @@ -109,6 +109,12 @@ std::vector MockSqliteReadStatement::values return valuesReturnStdVectorSource(reserveSize); } +template<> +ProjectPartNameIds MockSqliteReadStatement::values(std::size_t reserveSize) +{ + return valuesReturnProjectPartNameIds(reserveSize); +} + template <> Utils::optional MockSqliteReadStatement::value(const Utils::SmallStringView &text) diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h index 8ebcb6e13b9..0048fd62760 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.h +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,8 @@ using std::int64_t; namespace Sources = ClangBackEnd::Sources; using ClangBackEnd::PrecompiledHeaderTimeStamps; using ClangBackEnd::UsedMacros; +using ClangBackEnd::Internal::ProjectPartNameId; +using ClangBackEnd::Internal::ProjectPartNameIds; using ClangRefactoring::Symbol; using ClangRefactoring::Symbols; @@ -91,6 +94,8 @@ public: MOCK_METHOD2(valuesReturnFilePathIds, FilePathIds(std::size_t, int)); + MOCK_METHOD1(valuesReturnProjectPartNameIds, ProjectPartNameIds(std::size_t)); + MOCK_METHOD1(valueReturnInt32, Utils::optional(Utils::SmallStringView)); MOCK_METHOD2(valueReturnInt32, Utils::optional(int, Utils::SmallStringView)); @@ -226,9 +231,11 @@ std::vector MockSqliteReadStatement::values std::vector MockSqliteReadStatement::values(std::size_t reserveSize); -template <> -Utils::optional -MockSqliteReadStatement::value(const Utils::SmallStringView&); +template<> +ProjectPartNameIds MockSqliteReadStatement::values(std::size_t reserveSize); + +template<> +Utils::optional MockSqliteReadStatement::value(const Utils::SmallStringView &); template <> Utils::optional diff --git a/tests/unit/unittest/mocksymbolindexertaskqueue.h b/tests/unit/unittest/mocksymbolindexertaskqueue.h index 7fb0d3f0bd7..cef60ac7765 100644 --- a/tests/unit/unittest/mocksymbolindexertaskqueue.h +++ b/tests/unit/unittest/mocksymbolindexertaskqueue.h @@ -34,7 +34,6 @@ class MockSymbolIndexerTaskQueue : public ClangBackEnd::SymbolIndexerTaskQueueIn public: MOCK_METHOD1(addOrUpdateTasks, void (std::vector &&tasks)); - MOCK_METHOD1(removeTasks, - void (const std::vector &projectPartIds)); + MOCK_METHOD1(removeTasks, void(const ClangBackEnd::ProjectPartIds &projectPartIds)); MOCK_METHOD0(processEntries, void()); }; diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp index e97f60b9f50..ad5b57b4f52 100644 --- a/tests/unit/unittest/pchcreator-test.cpp +++ b/tests/unit/unittest/pchcreator-test.cpp @@ -91,7 +91,7 @@ protected: ClangBackEnd::FilePathId id(ClangBackEnd::FilePathView path) { - return creator.filePathCache().filePathId(path); + return filePathCache.filePathId(path); } FilePathIds sorted(FilePathIds &&filePathIds) @@ -104,17 +104,17 @@ protected: protected: Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer databaseInitializer{database}; + ClangBackEnd::FilePathCaching filePathCache{database}; FilePath main1Path = TESTDATA_DIR "/builddependencycollector/project/main3.cpp"; FilePath main2Path = TESTDATA_DIR "/builddependencycollector/project/main2.cpp"; FilePath header1Path = TESTDATA_DIR "/builddependencycollector/project/header1.h"; FilePath header2Path = TESTDATA_DIR "/builddependencycollector/project/header2.h"; FilePath generatedFilePath = TESTDATA_DIR "/builddependencycollector/project/generated_file.h"; TestEnvironment environment; - FileContainer generatedFile{generatedFilePath.clone(), "#pragma once", {}}; + FileContainer generatedFile{generatedFilePath.clone(), id(generatedFilePath), "#pragma once", {}}; NiceMock mockPchManagerClient; NiceMock mockClangPathWatcher; NiceMock mockBuildDependenciesStorage; - ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::PchCreator creator{environment, filePathCache, mockPchManagerClient, diff --git a/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp b/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp index 194f52afd3b..e468521a545 100644 --- a/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp +++ b/tests/unit/unittest/pchmanagerclientserverinprocess-test.cpp @@ -117,7 +117,7 @@ TEST_F(PchManagerClientServerInProcess, SendUpdateProjectPartsMessage) TEST_F(PchManagerClientServerInProcess, SendUpdateGeneratedFilesMessage) { - FileContainer fileContainer{{"/path/to/", "file"}, "content", {}}; + FileContainer fileContainer{{"/path/to/", "file"}, 1, "content", {}}; UpdateGeneratedFilesMessage message{{fileContainer}}; EXPECT_CALL(mockPchManagerServer, updateGeneratedFiles(message)); diff --git a/tests/unit/unittest/pchmanagerserver-test.cpp b/tests/unit/unittest/pchmanagerserver-test.cpp index d7e6c492f9a..bf14b628b8d 100644 --- a/tests/unit/unittest/pchmanagerserver-test.cpp +++ b/tests/unit/unittest/pchmanagerserver-test.cpp @@ -27,6 +27,7 @@ #include "mockbuilddependenciesstorage.h" #include "mockclangpathwatcher.h" +#include "mockfilepathcaching.h" #include "mockgeneratedfiles.h" #include "mockpchmanagerclient.h" #include "mockpchtaskgenerator.h" @@ -77,11 +78,13 @@ protected: Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; ClangBackEnd::FilePathCaching filePathCache{database}; + NiceMock mockFilePathCache; ClangBackEnd::PchManagerServer server{mockClangPathWatcher, mockPchTaskGenerator, mockProjectPartsManager, mockGeneratedFiles, - mockBuildDependenciesStorage}; + mockBuildDependenciesStorage, + mockFilePathCache}; NiceMock mockPchManagerClient; ClangBackEnd::ProjectPartId projectPartId1{1}; ClangBackEnd::ProjectPartId projectPartId2{2}; @@ -98,7 +101,7 @@ protected: projectPartId1, {"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"}, {{"DEFINE", "1", 1}}, - {{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, + {{TESTDATA_DIR "/symbolscollector/include", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, {{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}}, {id(header1Path)}, {id(main1Path)}, @@ -110,7 +113,7 @@ protected: {"-x", "c++-header", "-Wno-pragma-once-outside-header"}, {{"DEFINE", "1", 1}}, {{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, - {{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}}, + {{TESTDATA_DIR "/builddependencycollector", 1, ClangBackEnd::IncludeSearchPathType::User}}, {id(header2Path)}, {id(main2Path)}, Utils::Language::C, @@ -165,7 +168,7 @@ protected: std::vector projectParts2{projectPart2}; std::vector projectParts3{projectPart3}; std::vector projectParts4{projectPart3, projectPart4}; - FileContainer generatedFile{{"/path/to/", "file"}, "content", {}}; + FileContainer generatedFile{{"/path/to/", "file"}, id("/path/to/file"), "content", {}}; ClangBackEnd::UpdateProjectPartsMessage updateProjectPartsMessage{ Utils::clone(projectParts), {"toolChainArgument"}}; ClangBackEnd::RemoveProjectPartsMessage removeProjectPartsMessage{ @@ -226,7 +229,8 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier) mockPchTaskGenerator, mockProjectPartsManager, mockGeneratedFiles, - mockBuildDependenciesStorage}; + mockBuildDependenciesStorage, + filePathCache}; } TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds) @@ -419,4 +423,20 @@ TEST_F(PchManagerServer, SentUpToDateProjectPartIdsToClient) server.updateProjectParts(updateProjectPartsMessage.clone()); } + +TEST_F(PchManagerServer, AddingIncludesToFileCacheForProjectUpdates) +{ + InSequence s; + + EXPECT_CALL(mockFilePathCache, populateIfEmpty()); + EXPECT_CALL(mockFilePathCache, + addFilePaths(AllOf( + Contains(Eq(TESTDATA_DIR "/symbolscollector/include/unmodified_header.h")), + Contains(Eq(TESTDATA_DIR "/symbolscollector/include/unmodified_header2.h")), + Contains(Eq(TESTDATA_DIR "/builddependencycollector/project/header2.h")), + Contains(Eq(TESTDATA_DIR "/builddependencycollector/external/external3.h"))))); + EXPECT_CALL(mockProjectPartsManager, update(_)); + + server.updateProjectParts(updateProjectPartsMessage.clone()); +} } // namespace diff --git a/tests/unit/unittest/projectpartsstorage-test.cpp b/tests/unit/unittest/projectpartsstorage-test.cpp index 6c887ca3f06..b67cd5a37c4 100644 --- a/tests/unit/unittest/projectpartsstorage-test.cpp +++ b/tests/unit/unittest/projectpartsstorage-test.cpp @@ -29,11 +29,13 @@ #include #include +#include #include #include #include #include #include + namespace { using ClangBackEnd::FilePathId; @@ -107,6 +109,7 @@ protected: MockSqliteReadStatement &fetchProjectPrecompiledHeaderPathStatement = storage.fetchProjectPrecompiledHeaderBuildTimeStatement; MockSqliteReadStatement &fetchProjectPrecompiledHeaderBuildTimeStatement = storage.fetchProjectPrecompiledHeaderBuildTimeStatement; MockSqliteWriteStatement &resetDependentIndexingTimeStampsStatement = storage.resetDependentIndexingTimeStampsStatement; + MockSqliteReadStatement &fetchAllProjectPartNamesAndIdsStatement = storage.fetchAllProjectPartNamesAndIdsStatement; IncludeSearchPaths systemIncludeSearchPaths{{"/includes", 1, IncludeSearchPathType::BuiltIn}, {"/other/includes", 2, IncludeSearchPathType::System}}; IncludeSearchPaths projectIncludeSearchPaths{{"/project/includes", 1, IncludeSearchPathType::User}, @@ -124,6 +127,7 @@ protected: Utils::Language::Cxx, Utils::LanguageVersion::CXX11, Utils::LanguageExtension::None}; + ClangBackEnd::Internal::ProjectPartNameIds projectPartNameIds{{"projectPartName", 2}}; }; TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithNonExistingProjectPartName) @@ -139,6 +143,17 @@ TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithNonExistingProjectPartName) storage.fetchProjectPartId("test"); } +TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithNonExistingProjectPartNameUnguarded) +{ + InSequence s; + + EXPECT_CALL(fetchProjectPartIdStatement, + valueReturnProjectPartId(TypedEq("test"))); + EXPECT_CALL(insertProjectPartNameStatement, write(TypedEq("test"))); + + storage.fetchProjectPartIdUnguarded("test"); +} + TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithExistingProjectPart) { InSequence s; @@ -153,6 +168,18 @@ TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithExistingProjectPart) storage.fetchProjectPartId("test"); } +TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithExistingProjectPartUnguarded) +{ + InSequence s; + + EXPECT_CALL(fetchProjectPartIdStatement, + valueReturnProjectPartId(TypedEq("test"))) + .WillOnce(Return(Utils::optional{20})); + EXPECT_CALL(insertProjectPartNameStatement, write(TypedEq("test"))).Times(0); + + storage.fetchProjectPartIdUnguarded("test"); +} + TEST_F(ProjectPartsStorage, CallsFetchProjectIdWithBusyDatabaset) { InSequence s; @@ -184,6 +211,18 @@ TEST_F(ProjectPartsStorage, FetchProjectIdWithNonExistingProjectPartName) ASSERT_THAT(id.projectPathId, 21); } +TEST_F(ProjectPartsStorage, FetchProjectIdWithNonExistingProjectPartNameUnguarded) +{ + ON_CALL(fetchProjectPartIdStatement, + valueReturnProjectPartId(TypedEq("test"))) + .WillByDefault(Return(Utils::optional{})); + ON_CALL(mockDatabase, lastInsertedRowId()).WillByDefault(Return(21)); + + auto id = storage.fetchProjectPartIdUnguarded("test"); + + ASSERT_THAT(id.projectPathId, 21); +} + TEST_F(ProjectPartsStorage, FetchProjectIdWithNonExistingProjectPartNameAndIsBusy) { InSequence s; @@ -211,6 +250,17 @@ TEST_F(ProjectPartsStorage, FetchProjectIdWithExistingProjectPartName) ASSERT_THAT(id.projectPathId, 20); } +TEST_F(ProjectPartsStorage, FetchProjectIdWithExistingProjectPartNameUnguarded) +{ + ON_CALL(fetchProjectPartIdStatement, + valueReturnProjectPartId(TypedEq("test"))) + .WillByDefault(Return(Utils::optional{20})); + + auto id = storage.fetchProjectPartIdUnguarded("test"); + + ASSERT_THAT(id.projectPathId, 20); +} + TEST_F(ProjectPartsStorage, FetchProjectPartName) { InSequence s; @@ -418,6 +468,7 @@ TEST_F(ProjectPartsStorage, FetchProjectPartArtefactBySourceIdCallsValueInStatem storage.fetchProjectPartArtefact(FilePathId{1}); } + TEST_F(ProjectPartsStorage, FetchProjectPartArtefactBySourceIdReturnArtefact) { EXPECT_CALL(getProjectPartArtefactsBySourceId, valueReturnProjectPartArtefact(1)) @@ -495,6 +546,34 @@ TEST_F(ProjectPartsStorage, ResetDependentIndexingTimeStampsIsBusy) storage.resetIndexingTimeStamps({projectPart1, projectPart2}); } +TEST_F(ProjectPartsStorage, FetchAllProjectPartNamesAndIdsCalls) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(fetchAllProjectPartNamesAndIdsStatement, valuesReturnProjectPartNameIds(_)) + .WillRepeatedly(Return(projectPartNameIds)); + EXPECT_CALL(mockDatabase, commit()); + + storage.fetchAllProjectPartNamesAndIds(); +} + +TEST_F(ProjectPartsStorage, FetchAllProjectPartNamesAndIdsCallsIsBusy) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(fetchAllProjectPartNamesAndIdsStatement, valuesReturnProjectPartNameIds(_)) + .WillOnce(Throw(Sqlite::StatementIsBusy{""})); + EXPECT_CALL(mockDatabase, rollback()); + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(fetchAllProjectPartNamesAndIdsStatement, valuesReturnProjectPartNameIds(_)) + .WillRepeatedly(Return(projectPartNameIds)); + EXPECT_CALL(mockDatabase, commit()); + + storage.fetchAllProjectPartNamesAndIds(); +} + class ProjectPartsStorageSlow : public testing::Test, public Data { using Storage = ClangBackEnd::ProjectPartsStorage; @@ -530,6 +609,15 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectPartId) ASSERT_THAT(first, Eq(second)); } +TEST_F(ProjectPartsStorageSlow, FetchProjectPartIdUnguarded) +{ + auto first = storage.fetchProjectPartId("test"); + + auto second = storage.fetchProjectPartIdUnguarded("test"); + + ASSERT_THAT(first, Eq(second)); +} + TEST_F(ProjectPartsStorageSlow, FetchProjectParts) { projectPart1.projectPartId = storage.fetchProjectPartId("project1"); @@ -563,4 +651,16 @@ TEST_F(ProjectPartsStorageSlow, ResetDependentIndexingTimeStamps) SourceTimeStamp{10, 34})); } +TEST_F(ProjectPartsStorageSlow, FetchAllProjectPartNamesAndIdsy) +{ + using ClangBackEnd::Internal::ProjectPartNameId; + auto id = storage.fetchProjectPartId("projectPartName"); + auto id2 = storage.fetchProjectPartId("projectPartName2"); + + auto values = storage.fetchAllProjectPartNamesAndIds(); + + ASSERT_THAT(values, + UnorderedElementsAre(ProjectPartNameId{"projectPartName", id}, + ProjectPartNameId{"projectPartName2", id2})); +} } // namespace diff --git a/tests/unit/unittest/projectupdater-test.cpp b/tests/unit/unittest/projectupdater-test.cpp index 73f5359df09..1b9f271687d 100644 --- a/tests/unit/unittest/projectupdater-test.cpp +++ b/tests/unit/unittest/projectupdater-test.cpp @@ -66,10 +66,11 @@ using testing::NiceMock; using testing::AnyNumber; using ClangBackEnd::CompilerMacro; +using ClangBackEnd::FilePath; using ClangBackEnd::IncludeSearchPath; using ClangBackEnd::IncludeSearchPathType; -using ClangBackEnd::V2::FileContainer; using ClangBackEnd::ProjectPartContainer; +using ClangBackEnd::V2::FileContainer; using CppTools::CompilerOptionsBuilder; using ProjectExplorer::HeaderPath; @@ -182,9 +183,18 @@ protected: CppTools::ProjectPart nonBuildingProjectPart; ProjectPartContainer expectedContainer; ProjectPartContainer expectedContainer2; - FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}}; - FileContainer generatedFile2{{"/path/to2", "header1.h"}, "content", {}}; - FileContainer generatedFile3{{"/path/to", "header2.h"}, "content", {}}; + FileContainer generatedFile{{"/path/to", "header1.h"}, + filePathCache.filePathId(FilePath{"/path/to", "header1.h"}), + "content", + {}}; + FileContainer generatedFile2{{"/path/to2", "header1.h"}, + filePathCache.filePathId(FilePath{"/path/to2", "header1.h"}), + "content", + {}}; + FileContainer generatedFile3{{"/path/to", "header2.h"}, + filePathCache.filePathId(FilePath{"/path/to", "header2.h"}), + "content", + {}}; }; TEST_F(ProjectUpdater, CallUpdateProjectParts) @@ -271,6 +281,7 @@ TEST_F(ProjectUpdater, CallPrecompiledHeaderRemovedInPchManagerProjectUpdater) TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer) { updater.setExcludedPaths({"/path/to/header1.h"}); + updater.fetchProjectPartIds({&projectPart}); auto container = updater.toProjectPartContainer(&projectPart); @@ -279,21 +290,23 @@ TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer) TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainersHaveSameSizeLikeProjectParts) { + updater.fetchProjectPartIds({&projectPart, &nonBuildingProjectPart}); + auto containers = updater.toProjectPartContainers( {&projectPart, &projectPart, &nonBuildingProjectPart}); ASSERT_THAT(containers, SizeIs(2)); } -TEST_F(ProjectUpdater, CallStorageInsideTransaction) +TEST_F(ProjectUpdater, ProjectPartIdsPrefetchingInsideTransaction) { InSequence s; CppTools::ProjectPart projectPart; projectPart.project = &project; projectPart.displayName = "project"; Utils::SmallString projectPartName = projectPart.id(); - MockSqliteTransactionBackend mockSqliteTransactionBackend; - MockProjectPartsStorage mockProjectPartsStorage; + NiceMock mockSqliteTransactionBackend; + NiceMock mockProjectPartsStorage; ON_CALL(mockProjectPartsStorage, transactionBackend()) .WillByDefault(ReturnRef(mockSqliteTransactionBackend)); ClangPchManager::ClangIndexingSettingsManager settingsManager; @@ -302,9 +315,11 @@ TEST_F(ProjectUpdater, CallStorageInsideTransaction) mockProjectPartsStorage, settingsManager}; - EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartId(Eq(projectPartName))); + EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin()); + EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartIdUnguarded(Eq(projectPartName))); + EXPECT_CALL(mockSqliteTransactionBackend, commit()); - updater.toProjectPartContainers({&projectPart}); + updater.fetchProjectPartIds({&projectPart}); } TEST_F(ProjectUpdater, CreateSortedExcludedPaths) @@ -476,7 +491,8 @@ TEST_F(ProjectUpdater, AddProjectFilesToFilePathCache) NiceMock mockFilePathCaching; ClangPchManager::ProjectUpdater updater{mockPchManagerServer, mockFilePathCaching, - projectPartsStorage}; + projectPartsStorage, + settingsManager}; EXPECT_CALL(mockFilePathCaching, addFilePaths(UnorderedElementsAre(Eq(headerPaths[0]), @@ -487,6 +503,39 @@ TEST_F(ProjectUpdater, AddProjectFilesToFilePathCache) updater.updateProjectParts({&projectPart}, {}); } -// test for update many time and get the same id +TEST_F(ProjectUpdater, FillProjectPartIdCacheAtCreation) +{ + NiceMock mockProjectPartsStorage; + + EXPECT_CALL(mockProjectPartsStorage, fetchAllProjectPartNamesAndIds()); + + ClangPchManager::ProjectUpdater updater{mockPchManagerServer, + filePathCache, + mockProjectPartsStorage, + settingsManager}; +} + +TEST_F(ProjectUpdater, DontFetchProjectPartIdFromDatabaseIfItIsInCache) +{ + projectPart.files.clear(); + NiceMock mockSqliteTransactionBackend; + NiceMock mockProjectPartsStorage; + ON_CALL(mockProjectPartsStorage, transactionBackend()) + .WillByDefault(ReturnRef(mockSqliteTransactionBackend)); + ON_CALL(mockProjectPartsStorage, fetchAllProjectPartNamesAndIds()) + .WillByDefault(Return( + ClangBackEnd::Internal::ProjectPartNameIds{{Utils::PathString(projectPart.id()), 55}})); + ClangPchManager::ProjectUpdater updater{mockPchManagerServer, + filePathCache, + mockProjectPartsStorage, + settingsManager}; + + EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin()).Times(0); + EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartId(_)).Times(0); + EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartIdUnguarded(_)).Times(0); + EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0); + + updater.updateProjectParts({&projectPart}, {}); +} } // namespace diff --git a/tests/unit/unittest/refactoringclientserverinprocess-test.cpp b/tests/unit/unittest/refactoringclientserverinprocess-test.cpp index 8b6237bfad8..344eb08f03c 100644 --- a/tests/unit/unittest/refactoringclientserverinprocess-test.cpp +++ b/tests/unit/unittest/refactoringclientserverinprocess-test.cpp @@ -129,8 +129,8 @@ TEST_F(RefactoringClientServerInProcess, RequestSourceRangesAndDiagnosticsForQue { RequestSourceRangesForQueryMessage message{ "functionDecl()", - {{{TESTDATA_DIR, "query_simplefunction.cpp"}, "void f();", {"cc"}, 1}}, - {{{TESTDATA_DIR, "query_simplefunction.h"}, "void f();", {}, 1}}}; + {{{TESTDATA_DIR, "query_simplefunction.cpp"}, 1, "void f();", {"cc"}, 1}}, + {{{TESTDATA_DIR, "query_simplefunction.h"}, 2, "void f();", {}, 1}}}; EXPECT_CALL(mockRefactoringServer, requestSourceRangesForQueryMessage(message)); @@ -143,12 +143,13 @@ TEST_F(RefactoringClientServerInProcess, RequestSourceRangesForQueryMessage) RequestSourceRangesForQueryMessage message{ "functionDecl()", {{{TESTDATA_DIR, "query_simplefunction.cpp"}, + 1, "void f();", { "cc", }, 1}}, - {{{TESTDATA_DIR, "query_simplefunction.h"}, "void f();", {}, 1}}}; + {{{TESTDATA_DIR, "query_simplefunction.h"}, 2, "void f();", {}, 1}}}; EXPECT_CALL(mockRefactoringServer, requestSourceRangesForQueryMessage(message)); @@ -182,7 +183,7 @@ TEST_F(RefactoringClientServerInProcess, SendUpdateProjectPartsMessage) TEST_F(RefactoringClientServerInProcess, SendUpdateGeneratedFilesMessage) { - FileContainer fileContainer{{"/path/to/", "file"}, "content", {}}; + FileContainer fileContainer{{"/path/to/", "file"}, 1, "content", {}}; UpdateGeneratedFilesMessage message{{fileContainer}}; EXPECT_CALL(mockRefactoringServer, updateGeneratedFiles(message)); diff --git a/tests/unit/unittest/refactoringprojectupdater-test.cpp b/tests/unit/unittest/refactoringprojectupdater-test.cpp index eddeefa24c7..8b16adc6196 100644 --- a/tests/unit/unittest/refactoringprojectupdater-test.cpp +++ b/tests/unit/unittest/refactoringprojectupdater-test.cpp @@ -64,6 +64,10 @@ MATCHER_P(IsProjectPartContainer, class RefactoringProjectUpdater : public testing::Test { protected: + RefactoringProjectUpdater() + { + ON_CALL(mockProjectPartsStorage, transactionBackend()).WillByDefault(ReturnRef(database)); + } ProjectPart::Ptr createProjectPart(const char *name) { ProjectPart::Ptr projectPart{new ProjectPart}; @@ -115,8 +119,6 @@ TEST_F(RefactoringProjectUpdater, UpdateProjectPart) .WillRepeatedly(Return(QString(" project1"))); EXPECT_CALL(mockCppModelManager, projectPartForId(Eq(QString(" project1")))) .WillRepeatedly(Return(createProjectPart("project1"))); - EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartId(Eq(" project1"))) - .WillOnce(Return(ClangBackEnd::ProjectPartId{3})); EXPECT_CALL(mockRefactoringServer, updateProjectParts(Field(&UpdateProjectPartsMessage::projectsParts, ElementsAre(IsProjectPartContainer(3))))); diff --git a/tests/unit/unittest/refactoringserver-test.cpp b/tests/unit/unittest/refactoringserver-test.cpp index 74363de35fc..2cc3f26efd4 100644 --- a/tests/unit/unittest/refactoringserver-test.cpp +++ b/tests/unit/unittest/refactoringserver-test.cpp @@ -26,6 +26,7 @@ #include "googletest.h" #include "filesystem-utilities.h" +#include "mockfilepathcaching.h" #include "mockrefactoringclient.h" #include "mocksymbolindexing.h" #include "sourcerangecontainer-matcher.h" @@ -98,7 +99,11 @@ protected: ClangBackEnd::GeneratedFiles generatedFiles; ClangBackEnd::RefactoringServer refactoringServer{mockSymbolIndexing, filePathCache, generatedFiles}; Utils::SmallString sourceContent{"void f()\n {}"}; - FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, sourceContent.clone(), {"cc"}}; + ClangBackEnd::FilePath filePath{TESTDATA_DIR, "query_simplefunction.cpp"}; + FileContainer source{filePath.clone(), + filePathCache.filePathId(filePath), + sourceContent.clone(), + {"cc"}}; QTemporaryFile temporaryFile{Utils::TemporaryDirectory::masterDirectoryPath() + "/clangQuery-XXXXXX.cpp"}; int processingSlotCount = 2; @@ -126,9 +131,13 @@ TEST_F(RefactoringServerSlowTest, RequestSingleSourceRangesAndDiagnosticsWithUns { Utils::SmallString unsavedContent{"void f();"}; FileContainer source{{TESTDATA_DIR, "query_simplefunction.cpp"}, + filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.cpp"}), "#include \"query_simplefunction.h\"", {"cc"}}; - FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"}, unsavedContent.clone(), {}}; + FileContainer unsaved{{TESTDATA_DIR, "query_simplefunction.h"}, + filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.h"}), + unsavedContent.clone(), + {}}; RequestSourceRangesForQueryMessage message{"functionDecl()", {source.clone()}, {unsaved.clone()}}; EXPECT_CALL(mockRefactoringClient, @@ -240,6 +249,8 @@ TEST_F(RefactoringServerSlowTest, ForValidRequestSourceRangesAndDiagnosticsGetSo { RequestSourceRangesAndDiagnosticsForQueryMessage message("functionDecl()", {FilePath(temporaryFile.fileName()), + filePathCache.filePathId(FilePath( + temporaryFile.fileName())), "void f() {}", {"cc"}}); @@ -259,6 +270,8 @@ TEST_F(RefactoringServerSlowTest, ForInvalidRequestSourceRangesAndDiagnosticsGet { RequestSourceRangesAndDiagnosticsForQueryMessage message("func()", {FilePath(temporaryFile.fileName()), + filePathCache.filePathId(FilePath( + temporaryFile.fileName())), "void f() {}", {"cc"}}); @@ -277,6 +290,7 @@ TEST_F(RefactoringServerSlowTest, ForInvalidRequestSourceRangesAndDiagnosticsGet TEST_F(RefactoringServer, UpdateGeneratedFilesSetMemberWhichIsUsedForSymbolIndexing) { FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"}, + filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.h"}), "void f();", {}}}; @@ -288,6 +302,7 @@ TEST_F(RefactoringServer, UpdateGeneratedFilesSetMemberWhichIsUsedForSymbolIndex TEST_F(RefactoringServer, RemoveGeneratedFilesSetMemberWhichIsUsedForSymbolIndexing) { FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"}, + filePathCache.filePathId(FilePath{TESTDATA_DIR, "query_simplefunction.h"}), "void f();", {}}}; refactoringServer.updateGeneratedFiles(Utils::clone(unsaved)); @@ -297,8 +312,12 @@ TEST_F(RefactoringServer, RemoveGeneratedFilesSetMemberWhichIsUsedForSymbolIndex ASSERT_THAT(generatedFiles.fileContainers(), IsEmpty()); } -TEST_F(RefactoringServer, UpdateProjectPartsCallsSymbolIndexingUpdateProjectParts) +TEST_F(RefactoringServer, UpdateProjectPartsCalls) { + NiceMock mockFilePathCaching; + ClangBackEnd::RefactoringServer refactoringServer{mockSymbolIndexing, + mockFilePathCaching, + generatedFiles}; ProjectPartContainers projectParts{ {{1, {"-I", TESTDATA_DIR}, @@ -313,8 +332,8 @@ TEST_F(RefactoringServer, UpdateProjectPartsCallsSymbolIndexingUpdateProjectPart Utils::LanguageVersion::C11, Utils::LanguageExtension::All}}}; - EXPECT_CALL(mockSymbolIndexing, - updateProjectParts(projectParts)); + EXPECT_CALL(mockFilePathCaching, populateIfEmpty()); + EXPECT_CALL(mockSymbolIndexing, updateProjectParts(projectParts)); refactoringServer.updateProjectParts({Utils::clone(projectParts), {}}); } diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp index 127921ca985..25c7056f022 100644 --- a/tests/unit/unittest/symbolindexer-test.cpp +++ b/tests/unit/unittest/symbolindexer-test.cpp @@ -203,6 +203,7 @@ protected: Utils::LanguageVersion::CXX14, Utils::LanguageExtension::None}; FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"}, + filePathId(TESTDATA_DIR "/query_simplefunction.h"), "void f();", {}}}; SymbolEntries symbolEntries{{1, {"function", "function", SymbolKind::Function}}}; diff --git a/tests/unit/unittest/symbolscollector-test.cpp b/tests/unit/unittest/symbolscollector-test.cpp index cdefde2a31b..675a4af6d47 100644 --- a/tests/unit/unittest/symbolscollector-test.cpp +++ b/tests/unit/unittest/symbolscollector-test.cpp @@ -264,8 +264,10 @@ TEST_F(SymbolsCollector, ReferencedSymboldMatchesLocation) TEST_F(SymbolsCollector, DISABLED_ON_WINDOWS(CollectInUnsavedFile)) { - FileContainers unsaved{ - {{TESTDATA_DIR, "symbolscollector/generated_file.h"}, "void function();", {}}}; + FileContainers unsaved{{{TESTDATA_DIR, "symbolscollector/generated_file.h"}, + filePathId({TESTDATA_DIR, "symbolscollector/generated_file.h"}), + "void function();", + {}}}; collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/unsaved.cpp"), {"cc"}); collector.setUnsavedFiles(std::move(unsaved));