diff --git a/src/libs/clangsupport/clangsupport-lib.pri b/src/libs/clangsupport/clangsupport-lib.pri index 086755d5dca..0eaa7b8938d 100644 --- a/src/libs/clangsupport/clangsupport-lib.pri +++ b/src/libs/clangsupport/clangsupport-lib.pri @@ -110,6 +110,7 @@ HEADERS += \ $$PWD/clangsupportexceptions.h \ $$PWD/completionsmessage.h \ $$PWD/executeinloop.h \ + $$PWD/pchpaths.h \ $$PWD/projectpartid.h \ $$PWD/projectpartsstorage.h \ $$PWD/projectpartsstorageinterface.h \ diff --git a/src/libs/clangsupport/pchpaths.h b/src/libs/clangsupport/pchpaths.h new file mode 100644 index 00000000000..048ec9da8d1 --- /dev/null +++ b/src/libs/clangsupport/pchpaths.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "filepath.h" + +namespace ClangBackEnd { + +class PchPaths +{ +public: + PchPaths() = default; + PchPaths(Utils::SmallStringView projectPchPath, Utils::SmallStringView systemPchPath) + : projectPchPath(FilePathView{projectPchPath}) + , systemPchPath(FilePathView{systemPchPath}) + {} + + friend bool operator==(const PchPaths &first, const PchPaths &second) + { + return first.projectPchPath == second.projectPchPath + && first.systemPchPath == second.systemPchPath; + } + +public: + FilePath projectPchPath; + FilePath systemPchPath; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h index 26bc59d9e50..b8374b8413d 100644 --- a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h +++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h @@ -25,6 +25,7 @@ #pragma once +#include "pchpaths.h" #include "precompiledheaderstorageinterface.h" #include @@ -147,7 +148,8 @@ public: try { Sqlite::DeferredTransaction transaction{database}; - auto value = getPrecompiledHeader.template value(projectPartId.projectPathId); + auto value = fetchPrecompiledHeaderStatement.template value( + projectPartId.projectPathId); if (value) return *value; @@ -160,6 +162,25 @@ public: return FilePath(""); } + PchPaths fetchPrecompiledHeaders(ProjectPartId projectPartId) const + { + try { + Sqlite::DeferredTransaction transaction{database}; + + auto value = fetchPrecompiledHeadersStatement.template value( + projectPartId.projectPathId); + + if (value) + return *value; + + transaction.commit(); + } catch (const Sqlite::StatementIsBusy) { + return fetchPrecompiledHeaders(projectPartId); + } + + return {}; + } + public: Sqlite::ImmediateNonThrowingDestructorTransaction transaction; Database &database; @@ -183,10 +204,13 @@ public: database}; ReadStatement fetchSystemPrecompiledHeaderPathStatement{ "SELECT systemPchPath FROM precompiledHeaders WHERE projectPartId = ?", database}; - mutable ReadStatement getPrecompiledHeader{ + mutable ReadStatement fetchPrecompiledHeaderStatement{ "SELECT ifnull(nullif(projectPchPath, ''), systemPchPath) " "FROM precompiledHeaders WHERE projectPartId = ?", database}; + mutable ReadStatement fetchPrecompiledHeadersStatement{ + "SELECT projectPchPath, systemPchPath FROM precompiledHeaders WHERE projectPartId = ?", + database}; }; } diff --git a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h index 5937af3027e..2ce880cd6a7 100644 --- a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h +++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h @@ -27,7 +27,7 @@ #include "projectpartpch.h" -#include +#include #include #include @@ -56,6 +56,7 @@ public: virtual void deleteSystemPrecompiledHeaders(const ProjectPartIds &projectPartIds) = 0; virtual FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) = 0; virtual FilePath fetchPrecompiledHeader(ProjectPartId projectPartId) const = 0; + virtual PchPaths fetchPrecompiledHeaders(ProjectPartId projectPartId) const = 0; protected: ~PrecompiledHeaderStorageInterface() = default; diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp index 25b3bf41cd4..109e6c5e80a 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp @@ -101,26 +101,36 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart) if (!m_modifiedTimeChecker.isUpToDate(dependentTimeStamps)) { auto indexing = [projectPart = std::move(projectPart), sourcePathId, this]( SymbolsCollectorInterface &symbolsCollector) { - const FilePath pchPath = m_precompiledHeaderStorage.fetchPrecompiledHeader( - projectPart.projectPartId); + auto collect = [&](const FilePath &pchPath) { + using Builder = CommandLineBuilder; + Builder commandLineBuilder{projectPart, + projectPart.toolChainArguments, + InputFileType::Source, + {}, + {}, + pchPath}; + symbolsCollector.setFile(sourcePathId, commandLineBuilder.commandLine); - using Builder = CommandLineBuilder; - Builder commandLineBuilder{projectPart, - projectPart.toolChainArguments, - InputFileType::Source, - {}, - {}, - pchPath}; - symbolsCollector.setFile(sourcePathId, commandLineBuilder.commandLine); + return symbolsCollector.collectSymbols(); + }; - bool success = symbolsCollector.collectSymbols(); - - if (success) { + auto store = [&] { Sqlite::ImmediateTransaction transaction{m_transactionInterface}; m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses()); m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), symbolsCollector.sourceLocations()); transaction.commit(); + }; + + const PchPaths pchPaths = m_precompiledHeaderStorage.fetchPrecompiledHeaders( + projectPart.projectPartId); + + if (pchPaths.projectPchPath.size() && collect(pchPaths.projectPchPath)) { + store(); + } else if (pchPaths.systemPchPath.size() && collect(pchPaths.systemPchPath)) { + store(); + } else if (collect({})) { + store(); } }; @@ -166,23 +176,34 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId, auto indexing = [optionalArtefact = std::move(optionalArtefact), filePathId, this]( SymbolsCollectorInterface &symbolsCollector) { - const FilePath pchPath = m_precompiledHeaderStorage.fetchPrecompiledHeader( - optionalArtefact->projectPartId); - const ProjectPartArtefact &artefact = *optionalArtefact; + auto collect = [&](const FilePath &pchPath) { + const ProjectPartArtefact &artefact = *optionalArtefact; - CommandLineBuilder builder{ - artefact, artefact.toolChainArguments, InputFileType::Source, {}, {}, pchPath}; + using Builder = CommandLineBuilder; + Builder builder{artefact, artefact.toolChainArguments, InputFileType::Source, {}, {}, pchPath}; - symbolsCollector.setFile(filePathId, builder.commandLine); + symbolsCollector.setFile(filePathId, builder.commandLine); - bool success = symbolsCollector.collectSymbols(); + return symbolsCollector.collectSymbols(); + }; - if (success) { + auto store = [&] { Sqlite::ImmediateTransaction transaction{m_transactionInterface}; m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses()); m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(), symbolsCollector.sourceLocations()); transaction.commit(); + }; + + const PchPaths pchPaths = m_precompiledHeaderStorage.fetchPrecompiledHeaders( + optionalArtefact->projectPartId); + + if (pchPaths.projectPchPath.size() && collect(pchPaths.projectPchPath)) { + store(); + } else if (pchPaths.systemPchPath.size() && collect(pchPaths.systemPchPath)) { + store(); + } else if (collect({})) { + store(); } }; diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 84add6b4a11..6b3433ef104 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -39,27 +39,28 @@ #include #include #include -#include #include #include +#include +#include #include #include #include +#include #include #include #include +#include #include #include #include #include -#include -#include +#include #include #include -#include -#include +#include #include -#include +#include #include #include @@ -1289,6 +1290,10 @@ std::ostream &operator<<(std::ostream &out, const ProjectPartId &projectPathId) return out << projectPathId.projectPathId; } +std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths) +{ + return out << "(" << pchPaths.projectPchPath << ", " << pchPaths.systemPchPath << ")"; +} 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 2d83535d147..897a9f2a280 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -199,6 +199,7 @@ enum class IncludeSearchPathType : unsigned char; struct ArgumentsEntry; class ProjectPartContainer; class ProjectPartId; +class PchPaths; std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry); std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths); @@ -291,6 +292,7 @@ std::ostream &operator<<(std::ostream &out, const IncludeSearchPath &path); std::ostream &operator<<(std::ostream &out, const ArgumentsEntry &entry); std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &container); std::ostream &operator<<(std::ostream &out, const ProjectPartId &projectPathId); +std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths); void PrintTo(const FilePath &filePath, ::std::ostream *os); void PrintTo(const FilePathView &filePathView, ::std::ostream *os); diff --git a/tests/unit/unittest/mockprecompiledheaderstorage.h b/tests/unit/unittest/mockprecompiledheaderstorage.h index b6ca94d80b0..84caea55be5 100644 --- a/tests/unit/unittest/mockprecompiledheaderstorage.h +++ b/tests/unit/unittest/mockprecompiledheaderstorage.h @@ -49,4 +49,6 @@ public: ClangBackEnd::FilePath(ClangBackEnd::ProjectPartId projectPartId)); MOCK_CONST_METHOD1(fetchPrecompiledHeader, ClangBackEnd::FilePath(ClangBackEnd::ProjectPartId projectPartId)); + MOCK_CONST_METHOD1(fetchPrecompiledHeaders, + ClangBackEnd::PchPaths(ClangBackEnd::ProjectPartId projectPartId)); }; diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp index 2e9d74acf6b..b0df1ab75dc 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.cpp +++ b/tests/unit/unittest/mocksqlitereadstatement.cpp @@ -200,9 +200,15 @@ MockSqliteReadStatement::value(const int &proje return valueReturnProjectPartPch(projectPartId); } -template <> -Utils::optional -MockSqliteReadStatement::value(const int &sourceId) +template<> +Utils::optional MockSqliteReadStatement::value( + const int &projectPartId) +{ + return valueReturnPchPaths(projectPartId); +} + +template<> +Utils::optional MockSqliteReadStatement::value(const int &sourceId) { return valueReturnSmallString(sourceId); } diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h index 135a6d1851e..d952c90dec0 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.h +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -120,11 +121,11 @@ public: MOCK_METHOD1(valueReturnProjectPartContainer, Utils::optional(int)); MOCK_METHOD1(valuesReturnProjectPartContainers, ClangBackEnd::ProjectPartContainers(std::size_t)); - MOCK_METHOD1(valueReturnProjectPartPch, - Utils::optional(int)); + MOCK_METHOD1(valueReturnProjectPartPch, Utils::optional(int)); - MOCK_METHOD3(valuesReturnSymbols, - Symbols(std::size_t, int, Utils::SmallStringView)); + MOCK_METHOD1(valueReturnPchPaths, Utils::optional(int)); + + MOCK_METHOD3(valuesReturnSymbols, Symbols(std::size_t, int, Utils::SmallStringView)); MOCK_METHOD4(valuesReturnSymbols, Symbols(std::size_t, int, int, Utils::SmallStringView)); @@ -267,6 +268,10 @@ template<> Utils::optional MockSqliteReadStatement::value(const int &); +template<> +Utils::optional MockSqliteReadStatement::value( + const int &); + template<> ClangBackEnd::ProjectPartContainers MockSqliteReadStatement::values(std::size_t reserveSize); diff --git a/tests/unit/unittest/precompiledheaderstorage-test.cpp b/tests/unit/unittest/precompiledheaderstorage-test.cpp index fed3e52093a..9fb161d0eb5 100644 --- a/tests/unit/unittest/precompiledheaderstorage-test.cpp +++ b/tests/unit/unittest/precompiledheaderstorage-test.cpp @@ -47,7 +47,8 @@ protected: MockSqliteWriteStatement &insertSystemPrecompiledHeaderStatement = storage.insertSystemPrecompiledHeaderStatement; MockSqliteWriteStatement &deleteSystemPrecompiledHeaderStatement = storage.deleteSystemPrecompiledHeaderStatement; MockSqliteReadStatement &fetchSystemPrecompiledHeaderPathStatement = storage.fetchSystemPrecompiledHeaderPathStatement; - MockSqliteReadStatement &getPrecompiledHeader = storage.getPrecompiledHeader; + MockSqliteReadStatement &fetchPrecompiledHeaderStatement = storage.fetchPrecompiledHeaderStatement; + MockSqliteReadStatement &fetchPrecompiledHeadersStatement = storage.fetchPrecompiledHeadersStatement; }; TEST_F(PrecompiledHeaderStorage, UseTransaction) @@ -251,7 +252,7 @@ TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderReturnsNullOptional TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderCallsValueInStatement) { EXPECT_CALL(database, deferredBegin()); - EXPECT_CALL(getPrecompiledHeader, valueReturnFilePath(Eq(25))); + EXPECT_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25))); EXPECT_CALL(database, commit()); storage.fetchPrecompiledHeader(25); @@ -262,11 +263,11 @@ TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderIsBusy) InSequence s; EXPECT_CALL(database, deferredBegin()); - EXPECT_CALL(getPrecompiledHeader, valueReturnFilePath(Eq(25))) + EXPECT_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25))) .WillOnce(Throw(Sqlite::StatementIsBusy{""})); EXPECT_CALL(database, rollback()); EXPECT_CALL(database, deferredBegin()); - EXPECT_CALL(getPrecompiledHeader, valueReturnFilePath(Eq(25))); + EXPECT_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25))); EXPECT_CALL(database, commit()); storage.fetchPrecompiledHeader(25); @@ -275,7 +276,8 @@ TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderIsBusy) TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeader) { ClangBackEnd::FilePath pchFilePath{"/path/to/pch"}; - ON_CALL(getPrecompiledHeader, valueReturnFilePath(Eq(25))).WillByDefault(Return(pchFilePath)); + ON_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25))) + .WillByDefault(Return(pchFilePath)); auto path = storage.fetchPrecompiledHeader(25); @@ -288,4 +290,49 @@ TEST_F(PrecompiledHeaderStorage, FetchEmptyPrecompiledHeader) ASSERT_THAT(path, IsEmpty()); } + +TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderCalls) +{ + EXPECT_CALL(database, deferredBegin()); + EXPECT_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25))); + EXPECT_CALL(database, commit()); + + storage.fetchPrecompiledHeaders(25); +} + +TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeadersIsBusy) +{ + InSequence s; + + EXPECT_CALL(database, deferredBegin()); + EXPECT_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25))) + .WillOnce(Throw(Sqlite::StatementIsBusy{""})); + EXPECT_CALL(database, rollback()); + EXPECT_CALL(database, deferredBegin()); + EXPECT_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25))); + EXPECT_CALL(database, commit()); + + storage.fetchPrecompiledHeaders(25); +} + +TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaders) +{ + ClangBackEnd::PchPaths pchFilePaths{"/project/pch", "/system/pch"}; + ON_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25))) + .WillByDefault(Return(pchFilePaths)); + + auto paths = storage.fetchPrecompiledHeaders(25); + + ASSERT_THAT(paths, Eq(pchFilePaths)); +} + +TEST_F(PrecompiledHeaderStorage, FetchEmptyPrecompiledHeaders) +{ + auto paths = storage.fetchPrecompiledHeaders(25); + + ASSERT_THAT(paths, + AllOf(Field(&ClangBackEnd::PchPaths::projectPchPath, IsEmpty()), + Field(&ClangBackEnd::PchPaths::systemPchPath, IsEmpty()))); +} + } // namespace diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp index 673ef1b4caa..c1373e03c45 100644 --- a/tests/unit/unittest/symbolindexer-test.cpp +++ b/tests/unit/unittest/symbolindexer-test.cpp @@ -241,7 +241,7 @@ protected: ClangBackEnd::FileStatuses fileStatuses1{{1, 0, 32}}; ClangBackEnd::FileStatuses fileStatuses2{{2, 0, 35}}; Utils::optional nullArtefact; - ClangBackEnd::FilePath projectPchPath{"/path/to/pch"}; + ClangBackEnd::PchPaths pchPaths{"/project/pch", "/system/pch"}; NiceMock mockSqliteTransactionBackend; NiceMock mockSymbolStorage; NiceMock mockBuildDependenciesStorage; @@ -308,8 +308,8 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector) TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInCollector) { - ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(projectPart1.projectPartId))) - .WillByDefault(Return(projectPchPath)); + ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId))) + .WillByDefault(Return(pchPaths)); EXPECT_CALL(mockCollector, setFile(main1PathId, @@ -339,7 +339,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInColl "-Xclang", "-include-pch", "-Xclang", - toNativePath("/path/to/pch")))); + toNativePath("/project/pch")))); indexer.updateProjectParts({projectPart1}); } @@ -439,7 +439,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder) { InSequence s; - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(projectPart1.projectPartId))); + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId))); EXPECT_CALL(mockCollector, setFile(main1PathId, ElementsAre("clang++", @@ -473,11 +473,289 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder) indexer.updateProjectParts({projectPart1}); } -TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingSymbols) +TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsProjectAndSystemPchPathsAndHasNoError) { InSequence s; - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(projectPart1.projectPartId))); + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId))) + .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"})); + EXPECT_CALL(mockCollector, + setFile(main1PathId, + ElementsAre("clang++", + "-w", + "-Wno-pragma-once-outside-header", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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.updateProjectParts({projectPart1}); +} + +TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectPch) +{ + InSequence s; + + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId))) + .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"})); + EXPECT_CALL(mockCollector, + setFile(main1PathId, + ElementsAre("clang++", + "-w", + "-Wno-pragma-once-outside-header", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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(main1PathId, + ElementsAre("clang++", + "-w", + "-Wno-pragma-once-outside-header", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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.updateProjectParts({projectPart1}); +} + +TEST_F(SymbolIndexer, + UpdateProjectPartsCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectAndSystemPch) +{ + InSequence s; + + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId))) + .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"})); + EXPECT_CALL(mockCollector, + setFile(main1PathId, + ElementsAre("clang++", + "-w", + "-Wno-pragma-once-outside-header", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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(main1PathId, + ElementsAre("clang++", + "-w", + "-Wno-pragma-once-outside-header", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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(main1PathId, + ElementsAre("clang++", + "-w", + "-Wno-pragma-once-outside-header", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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.updateProjectParts({projectPart1}); +} + +TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsProjectAndSystemPchPathsAndHasOnlyError) +{ + InSequence s; + + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId))) + .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"})); + EXPECT_CALL(mockCollector, + setFile(main1PathId, + ElementsAre("clang++", + "-w", + "-Wno-pragma-once-outside-header", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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(main1PathId, + ElementsAre("clang++", + "-w", + "-Wno-pragma-once-outside-header", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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(main1PathId, ElementsAre("clang++", @@ -504,9 +782,86 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingS "-isystem", toNativePath("/includes")))); EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false)); - EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0); EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0); - EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0); + + indexer.updateProjectParts({projectPart1}); +} + +TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsSystemPchPathsAndHasErrorWithProjectPch) +{ + InSequence s; + + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId))) + .WillOnce(Return(ClangBackEnd::PchPaths{{}, "/system/pch"})); + EXPECT_CALL(mockCollector, + setFile(main1PathId, + ElementsAre("clang++", + "-w", + "-Wno-pragma-once-outside-header", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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.updateProjectParts({projectPart1}); +} + +TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsNoPchPathsAndHasErrors) +{ + InSequence s; + + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(projectPart1.projectPartId))); + EXPECT_CALL(mockCollector, + setFile(main1PathId, + ElementsAre("clang++", + "-w", + "-Wno-pragma-once-outside-header", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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.updateProjectParts({projectPart1}); } @@ -644,7 +999,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder) fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) .WillOnce(Return(artefact)); EXPECT_CALL(mockSqliteTransactionBackend, commit()); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))); + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))); EXPECT_CALL(mockCollector, setFile(Eq(sourceFileIds[0]), ElementsAre("clang++", @@ -686,7 +1041,7 @@ TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath) EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0])) .WillOnce(Return(nullArtefact)); EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(_)).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); @@ -696,18 +1051,302 @@ TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath) indexer.pathsChanged({sourceFileIds[0]}); } -TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrderButGetsAnErrorForCollectingSymbols) +TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasNoError) { InSequence s; - EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin()); EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) .WillOnce(Return(artefact)); - EXPECT_CALL(mockSqliteTransactionBackend, commit()); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))); + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))) + .WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"})); EXPECT_CALL(mockCollector, - setFile(Eq(sourceFileIds[0]), + setFile(sourceFileIds[0], + ElementsAre("clang++", + "-w", + "-DFOO", + "-DNOMINMAX", + "-x", + "c++", + "-std=c++14", + "-nostdinc", + "-nostdinc++", + "-DBAR=1", + "-DFOO=1", + "-I", + toNativePath(resourcePath()), + "-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", + "-I", + toNativePath(resourcePath()), + "-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", + "-I", + toNativePath(resourcePath()), + "-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", + "-I", + toNativePath(resourcePath()), + "-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", + "-I", + toNativePath(resourcePath()), + "-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", + "-I", + toNativePath(resourcePath()), + "-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", + "-I", + toNativePath(resourcePath()), + "-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", + "-I", + toNativePath(resourcePath()), + "-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", @@ -732,9 +1371,92 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrderButGetsAnErrorForCollectingSy "-isystem", toNativePath("/includes")))); EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false)); - EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0); EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0); - EXPECT_CALL(mockSqliteTransactionBackend, commit()).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", + "-I", + toNativePath(resourcePath()), + "-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", + "-I", + toNativePath(resourcePath()), + "-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]}); } @@ -743,8 +1465,8 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader) { ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) .WillByDefault(Return(artefact)); - ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))) - .WillByDefault(Return(projectPchPath)); + ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId))) + .WillByDefault(Return(pchPaths)); std::vector symbolIndexerTask; EXPECT_CALL(mockCollector, @@ -775,7 +1497,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader) "-Xclang", "-include-pch", "-Xclang", - toNativePath("/path/to/pch")))); + toNativePath("/project/pch")))); indexer.pathsChanged({sourceFileIds[0]}); }