From 5ab057746c662aba3308eff99e48c1e6bcc2b51e Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Sun, 7 Apr 2019 20:46:06 +0200 Subject: [PATCH] CppTools: Add pre system include search path per project Sometimes you want add a pre system include search path per project to overload some system header for indexing. This can then even be checked in the repository. Change-Id: Ib103e5935d0553aa94522ed736f8c4eb2405a093 Reviewed-by: Ivan Donchevskii --- src/plugins/cpptools/headerpathfilter.cpp | 16 +++ src/plugins/cpptools/headerpathfilter.h | 2 + tests/unit/mockup/projectexplorer/project.h | 4 +- .../clangqueryprojectfindfilter-test.cpp | 113 +++++++++--------- tests/unit/unittest/headerpathfilter-test.cpp | 9 +- tests/unit/unittest/projectupdater-test.cpp | 31 +++-- .../unit/unittest/refactoringclient-test.cpp | 44 +++---- .../unit/unittest/refactoringengine-test.cpp | 26 ++-- .../refactoringprojectupdater-test.cpp | 4 + 9 files changed, 143 insertions(+), 106 deletions(-) diff --git a/src/plugins/cpptools/headerpathfilter.cpp b/src/plugins/cpptools/headerpathfilter.cpp index b514c468d76..98c4579cbae 100644 --- a/src/plugins/cpptools/headerpathfilter.cpp +++ b/src/plugins/cpptools/headerpathfilter.cpp @@ -29,6 +29,8 @@ #include #endif +#include + #include namespace CppTools { @@ -41,6 +43,8 @@ void HeaderPathFilter::process() { const HeaderPaths &headerPaths = projectPart.headerPaths; + addPreIncludesPath(); + for (const HeaderPath &headerPath : headerPaths) filterHeaderPath(headerPath); @@ -141,6 +145,18 @@ void HeaderPathFilter::tweakHeaderPaths() } } +void HeaderPathFilter::addPreIncludesPath() +{ + if (projectDirectory.size()) { + Utils::FileName rootProjectDirectory = Utils::FileName::fromString(projectDirectory); + + rootProjectDirectory.appendPath(".pre_includes"); + + systemHeaderPaths.push_back( + {rootProjectDirectory.toString(), ProjectExplorer::HeaderPathType::System}); + } +} + QString HeaderPathFilter::ensurePathWithSlashEnding(const QString &path) { QString pathWithSlashEnding = path; diff --git a/src/plugins/cpptools/headerpathfilter.h b/src/plugins/cpptools/headerpathfilter.h index 8b4e7719942..20fbc020e88 100644 --- a/src/plugins/cpptools/headerpathfilter.h +++ b/src/plugins/cpptools/headerpathfilter.h @@ -53,6 +53,8 @@ private: void tweakHeaderPaths(); + void addPreIncludesPath(); + bool isProjectHeaderPath(const QString &path) const; static QString ensurePathWithSlashEnding(const QString &path); diff --git a/tests/unit/mockup/projectexplorer/project.h b/tests/unit/mockup/projectexplorer/project.h index cca7e49127d..e6e321ee433 100644 --- a/tests/unit/mockup/projectexplorer/project.h +++ b/tests/unit/mockup/projectexplorer/project.h @@ -39,8 +39,10 @@ public: Utils::FileName projectDirectory() const { return {}; } - Utils::FileName rootProjectDirectory() const { return {}; } + Utils::FileName rootProjectDirectory() const { return rootProjectDirectoryPath; } Target *activeTarget() const { return {}; } + + Utils::FileName rootProjectDirectoryPath; }; } // namespace ProjectExplorer diff --git a/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp b/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp index 5ff87f60595..39819809029 100644 --- a/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp +++ b/tests/unit/unittest/clangqueryprojectfindfilter-test.cpp @@ -37,6 +37,7 @@ #include #include +#include namespace { @@ -53,11 +54,62 @@ using testing::ByMove; using CppTools::CompilerOptionsBuilder; using ClangBackEnd::V2::FileContainer; +std::vector createCommandLines( + const std::vector &projectParts) +{ + using Filter = ClangRefactoring::ClangQueryProjectsFindFilter; + + std::vector commandLines; + + for (const CppTools::ProjectPart::Ptr &projectPart : projectParts) { + for (const CppTools::ProjectFile &projectFile : projectPart->files) { + Utils::SmallStringVector commandLine = Filter::compilerArguments(projectPart.data(), + projectFile.kind); + commandLine.emplace_back(projectFile.path); + commandLines.push_back(commandLine); + } + } + + return commandLines; +} + class ClangQueryProjectFindFilter : public ::testing::Test { protected: - void SetUp(); - std::unique_ptr createSearchHandle(); + void SetUp() + { + projectsParts = createProjectParts(); + commandLines = createCommandLines(projectsParts); + + findFilter.setProjectParts(projectsParts); + findFilter.setUnsavedContent({unsavedContent.clone()}); + + ON_CALL(mockSearch, startNewSearch(QStringLiteral("Clang Query"), findDeclQueryText)) + .WillByDefault(Return(ByMove(createSearchHandle()))); + } + std::unique_ptr createSearchHandle() + { + auto handle = std::make_unique>(); + handle->setRefactoringServer(&mockRefactoringServer); + + return handle; + } + + std::vector createProjectParts() + { + auto projectPart1 = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); + projectPart1->project = &project; + projectPart1->files.append({"/path/to/file1.h", CppTools::ProjectFile::CXXHeader}); + projectPart1->files.append({"/path/to/file1.cpp", CppTools::ProjectFile::CXXSource}); + + auto projectPart2 = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); + projectPart2->project = &project; + projectPart2->files.append({"/path/to/file2.cpp", CppTools::ProjectFile::CXXSource}); + projectPart2->files.append({"/path/to/unsaved.cpp", CppTools::ProjectFile::CXXSource}); + projectPart2->files.append({"/path/to/cheader.h", CppTools::ProjectFile::CHeader}); + + return {projectPart1, projectPart2}; + } protected: NiceMock mockRefactoringServer; @@ -73,6 +125,7 @@ protected: ClangBackEnd::V2::FileContainer unsavedContent{{"/path/to", "unsaved.cpp"}, "void f();", {}}; + ProjectExplorer::Project project; }; TEST_F(ClangQueryProjectFindFilter, SupportedFindFlags) @@ -175,60 +228,4 @@ TEST_F(ClangQueryProjectFindFilter, CallingRequestSourceRangesAndDiagnostics) findFilter.requestSourceRangesAndDiagnostics(QString(queryText), QString(exampleContent)); } -std::vector createProjectParts() -{ - auto projectPart1 = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); - projectPart1->files.append({"/path/to/file1.h", CppTools::ProjectFile::CXXHeader}); - projectPart1->files.append({"/path/to/file1.cpp", CppTools::ProjectFile::CXXSource}); - - auto projectPart2 = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); - projectPart2->files.append({"/path/to/file2.cpp", CppTools::ProjectFile::CXXSource}); - projectPart2->files.append({"/path/to/unsaved.cpp", CppTools::ProjectFile::CXXSource}); - projectPart2->files.append({"/path/to/cheader.h", CppTools::ProjectFile::CHeader}); - - - return {projectPart1, projectPart2}; -} - -std::vector -createCommandLines(const std::vector &projectParts) -{ - using Filter = ClangRefactoring::ClangQueryProjectsFindFilter; - - std::vector commandLines; - - for (const CppTools::ProjectPart::Ptr &projectPart : projectParts) { - for (const CppTools::ProjectFile &projectFile : projectPart->files) { - Utils::SmallStringVector commandLine = Filter::compilerArguments(projectPart.data(), - projectFile.kind); - commandLine.emplace_back(projectFile.path); - commandLines.push_back(commandLine); - } - } - - return commandLines; -} - -void ClangQueryProjectFindFilter::SetUp() -{ - projectsParts = createProjectParts(); - commandLines = createCommandLines(projectsParts); - - findFilter.setProjectParts(projectsParts); - findFilter.setUnsavedContent({unsavedContent.clone()}); - - - ON_CALL(mockSearch, startNewSearch(QStringLiteral("Clang Query"), findDeclQueryText)) - .WillByDefault(Return(ByMove(createSearchHandle()))); - -} - -std::unique_ptr ClangQueryProjectFindFilter::createSearchHandle() -{ - auto handle = std::make_unique>(); - handle->setRefactoringServer(&mockRefactoringServer); - - return handle; -} - } diff --git a/tests/unit/unittest/headerpathfilter-test.cpp b/tests/unit/unittest/headerpathfilter-test.cpp index 7caa3a15dc5..79091e0a0b2 100644 --- a/tests/unit/unittest/headerpathfilter-test.cpp +++ b/tests/unit/unittest/headerpathfilter-test.cpp @@ -26,6 +26,7 @@ #include "googletest.h" #include +#include namespace { @@ -80,9 +81,11 @@ protected: HeaderPath{"/project/user_path", HeaderPathType::User}}; projectPart.headerPaths = headerPaths; + projectPart.project = &project; } protected: + ProjectExplorer::Project project; CppTools::ProjectPart projectPart; CppTools::HeaderPathFilter filter{ projectPart, CppTools::UseTweakedHeaderPaths::No, {}, {}, "/project", "/build"}; @@ -100,7 +103,8 @@ TEST_F(HeaderPathFilter, System) filter.process(); ASSERT_THAT(filter.systemHeaderPaths, - ElementsAre(HasSystem("/system_path"), + ElementsAre(HasSystem("/project/.pre_includes"), + HasSystem("/system_path"), HasFramework("/framework_path"), HasUser("/outside_project_user_path"), HasUser("/buildb/user_path"), @@ -137,7 +141,8 @@ TEST_F(HeaderPathFilter, DontAddInvalidPath) AllOf(Field(&CppTools::HeaderPathFilter::builtInHeaderPaths, ElementsAre(HasBuiltIn("/builtin_path"))), Field(&CppTools::HeaderPathFilter::systemHeaderPaths, - ElementsAre(HasSystem("/system_path"), + ElementsAre(HasSystem("/project/.pre_includes"), + HasSystem("/system_path"), HasFramework("/framework_path"), HasUser("/outside_project_user_path"), HasUser("/buildb/user_path"), diff --git a/tests/unit/unittest/projectupdater-test.cpp b/tests/unit/unittest/projectupdater-test.cpp index 8e52ca35eeb..7a714533faa 100644 --- a/tests/unit/unittest/projectupdater-test.cpp +++ b/tests/unit/unittest/projectupdater-test.cpp @@ -46,9 +46,10 @@ #include #include -#include #include #include +#include +#include #include @@ -85,6 +86,8 @@ protected: void SetUp() override { + project.rootProjectDirectoryPath.appendPath("project"); + projectPart.project = &project; projectPart.files.push_back(header1ProjectFile); projectPart.files.push_back(header2ProjectFile); projectPart.files.push_back(source1ProjectFile); @@ -94,6 +97,7 @@ protected: projectPart.projectMacros = {{"FOO", "2"}, {"BAR", "1"}}; projectPartId = projectPartsStorage.fetchProjectPartId(Utils::SmallString{projectPart.id()}); + projectPart2.project = &project; projectPart2.files.push_back(header2ProjectFile); projectPart2.files.push_back(header1ProjectFile); projectPart2.files.push_back(source2ProjectFile); @@ -115,7 +119,8 @@ protected: expectedContainer = {projectPartId, arguments.clone(), Utils::clone(compilerMacros), - {{CLANG_RESOURCE_DIR, 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, + {{"project/.pre_includes", 1, ClangBackEnd::IncludeSearchPathType::System}, + {CLANG_RESOURCE_DIR, 2, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, {}, {filePathId(headerPaths[1])}, {filePathIds(sourcePaths)}, @@ -125,7 +130,8 @@ protected: expectedContainer2 = {projectPartId2, arguments2.clone(), Utils::clone(compilerMacros), - {{CLANG_RESOURCE_DIR, 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, + {{"project/.pre_includes", 1, ClangBackEnd::IncludeSearchPathType::System}, + {CLANG_RESOURCE_DIR, 2, ClangBackEnd::IncludeSearchPathType::BuiltIn}}, {}, {filePathId(headerPaths[1])}, {filePathIds(sourcePaths)}, @@ -159,6 +165,7 @@ protected: CppTools::ProjectFile cannotBuildSourceProjectFile{QString("/cannot/build"), CppTools::ProjectFile::CXXSource}; CppTools::ProjectFile nonActiveProjectFile{QString("/foo"), CppTools::ProjectFile::CXXSource, false}; + ProjectExplorer::Project project; CppTools::ProjectPart projectPart; CppTools::ProjectPart projectPart2; CppTools::ProjectPart nonBuildingProjectPart; @@ -269,6 +276,7 @@ TEST_F(ProjectUpdater, CallStorageInsideTransaction) { InSequence s; CppTools::ProjectPart projectPart; + projectPart.project = &project; projectPart.displayName = "project"; Utils::SmallString projectPartName = projectPart.id(); MockSqliteTransactionBackend mockSqliteTransactionBackend; @@ -305,6 +313,7 @@ TEST_F(ProjectUpdater, CreateSortedCompilerMacros) TEST_F(ProjectUpdater, CreateSortedIncludeSearchPaths) { CppTools::ProjectPart projectPart; + projectPart.project = &project; ProjectExplorer::HeaderPath includePath{"/to/path1", ProjectExplorer::HeaderPathType::User}; ProjectExplorer::HeaderPath includePath2{"/to/path2", ProjectExplorer::HeaderPathType::User}; ProjectExplorer::HeaderPath invalidPath; @@ -317,13 +326,15 @@ TEST_F(ProjectUpdater, CreateSortedIncludeSearchPaths) auto paths = updater.createIncludeSearchPaths(projectPart); - ASSERT_THAT(paths.system, - ElementsAre(Eq(IncludeSearchPath{systemPath.path, 1, IncludeSearchPathType::System}), - Eq(IncludeSearchPath{builtInPath.path, 4, IncludeSearchPathType::BuiltIn}), - Eq(IncludeSearchPath{frameworkPath.path, 2, IncludeSearchPathType::Framework}), - Eq(IncludeSearchPath{CLANG_RESOURCE_DIR, - 3, - ClangBackEnd::IncludeSearchPathType::BuiltIn}))); + ASSERT_THAT( + paths.system, + ElementsAre(Eq(IncludeSearchPath{systemPath.path, 2, IncludeSearchPathType::System}), + Eq(IncludeSearchPath{builtInPath.path, 5, IncludeSearchPathType::BuiltIn}), + Eq(IncludeSearchPath{frameworkPath.path, 3, IncludeSearchPathType::Framework}), + Eq(IncludeSearchPath{"project/.pre_includes", 1, IncludeSearchPathType::System}), + Eq(IncludeSearchPath{CLANG_RESOURCE_DIR, + 4, + ClangBackEnd::IncludeSearchPathType::BuiltIn}))); ASSERT_THAT(paths.project, ElementsAre(Eq(IncludeSearchPath{includePath.path, 2, IncludeSearchPathType::User}), Eq(IncludeSearchPath{includePath2.path, 1, IncludeSearchPathType::User}))); diff --git a/tests/unit/unittest/refactoringclient-test.cpp b/tests/unit/unittest/refactoringclient-test.cpp index 37b6e2a7446..57a3b93156b 100644 --- a/tests/unit/unittest/refactoringclient-test.cpp +++ b/tests/unit/unittest/refactoringclient-test.cpp @@ -38,6 +38,7 @@ #include #include +#include #include @@ -63,7 +64,26 @@ using Utils::SmallStringVector; class RefactoringClient : public ::testing::Test { - void SetUp(); + void SetUp() + { + using Filter = ClangRefactoring::ClangQueryProjectsFindFilter; + + client.setRefactoringEngine(&engine); + + projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); + projectPart->project = &project; + projectPart->files.push_back(projectFile); + + commandLine = Filter::compilerArguments(projectPart.data(), projectFile.kind); + + client.setSearchHandle(&mockSearchHandle); + client.setExpectedResultCount(1); + + ON_CALL(mockFilePathCaching, filePath(Eq(FilePathId{1}))) + .WillByDefault(Return(FilePath(PathString("/path/to/file")))); + ON_CALL(mockFilePathCaching, filePath(Eq(FilePathId{42}))) + .WillByDefault(Return(clangBackEndFilePath)); + } protected: NiceMock mockFilePathCaching; @@ -84,6 +104,7 @@ protected: Utils::FileName filePath{Utils::FileName::fromString(qStringFilePath)}; ClangBackEnd::FilePath clangBackEndFilePath{qStringFilePath}; SmallStringVector commandLine; + ProjectExplorer::Project project; CppTools::ProjectPart::Ptr projectPart; CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource}; SourceLocationsForRenamingMessage renameMessage{"symbol", @@ -228,25 +249,4 @@ TEST_F(RefactoringClient, SetProgress) client.progress({ClangBackEnd::ProgressType::Indexing, 10, 20}); } - -void RefactoringClient::SetUp() -{ - using Filter = ClangRefactoring::ClangQueryProjectsFindFilter; - - client.setRefactoringEngine(&engine); - - projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); - projectPart->files.push_back(projectFile); - - commandLine = Filter::compilerArguments(projectPart.data(), projectFile.kind); - - client.setSearchHandle(&mockSearchHandle); - client.setExpectedResultCount(1); - - ON_CALL(mockFilePathCaching, filePath(Eq(FilePathId{1}))) - .WillByDefault(Return(FilePath(PathString("/path/to/file")))); - ON_CALL(mockFilePathCaching, filePath(Eq(FilePathId{42}))) - .WillByDefault(Return(clangBackEndFilePath)); -} - } diff --git a/tests/unit/unittest/refactoringengine-test.cpp b/tests/unit/unittest/refactoringengine-test.cpp index 747c9300900..e24a6361f92 100644 --- a/tests/unit/unittest/refactoringengine-test.cpp +++ b/tests/unit/unittest/refactoringengine-test.cpp @@ -36,6 +36,7 @@ #include #include +#include #include @@ -56,7 +57,17 @@ using Utils::SmallStringVector; class RefactoringEngine : public ::testing::Test { protected: - void SetUp(); + void SetUp() + { + projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); + projectPart->project = &project; + projectPart->files.push_back(projectFile); + + CompilerOptionsBuilder optionsBuilder(*projectPart); + commandLine = Utils::SmallStringVector( + optionsBuilder.build(projectFile.kind, CppTools::UsePrecompiledHeaders::No)); + commandLine.push_back(qStringFilePath); + } protected: NiceMock mockFilePathCaching; @@ -74,6 +85,7 @@ protected: Utils::FileName filePath{Utils::FileName::fromString(qStringFilePath)}; ClangBackEnd::FilePath clangBackEndFilePath{qStringFilePath}; SmallStringVector commandLine; + ProjectExplorer::Project project; CppTools::ProjectPart::Ptr projectPart; CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource}; }; @@ -143,17 +155,5 @@ TEST_F(RefactoringEngine, ServerIsUsableForUsableEngine) ASSERT_TRUE(mockRefactoringServer.isAvailable()); } - -void RefactoringEngine::SetUp() -{ - projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart); - projectPart->files.push_back(projectFile); - - CompilerOptionsBuilder optionsBuilder(*projectPart); - commandLine = Utils::SmallStringVector( - optionsBuilder.build(projectFile.kind, CppTools::UsePrecompiledHeaders::No)); - commandLine.push_back(qStringFilePath); -} - } diff --git a/tests/unit/unittest/refactoringprojectupdater-test.cpp b/tests/unit/unittest/refactoringprojectupdater-test.cpp index 028edc0f7f0..8d5e60df91a 100644 --- a/tests/unit/unittest/refactoringprojectupdater-test.cpp +++ b/tests/unit/unittest/refactoringprojectupdater-test.cpp @@ -41,6 +41,8 @@ #include +#include + #include namespace { @@ -64,6 +66,7 @@ protected: ProjectPart::Ptr createProjectPart(const char *name) { ProjectPart::Ptr projectPart{new ProjectPart}; + projectPart->project = &project; projectPart->displayName = QString::fromUtf8(name, std::strlen(name)); projectPartId = projectPart->id(); return projectPart; @@ -80,6 +83,7 @@ protected: ClangPchManager::PchManagerClient pchManagerClient{mockPchCreationProgressManager, mockDependencyCreationProgressManager}; MockCppModelManager mockCppModelManager; + ProjectExplorer::Project project; ClangRefactoring::RefactoringProjectUpdater updater{mockRefactoringServer, pchManagerClient, mockCppModelManager,