From 7d30709306ff5fb6148c6bc8d08c2fcc7a872877 Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Mon, 21 Jan 2019 15:18:31 +0100 Subject: [PATCH] logic: Fixes and improvements for C/C++ compiler header path handling * Always add compiler header path when prefilling on first start, regardless of successful detection * Show compiler header path in path list box on top and readonly * Prepend compiler header path on Windows in system header path compiler flags, append otherwise * Show warning when saving ApplicationSettings if compiler header path is not in global include paths * Show warning when saving ApplicationSettings if there is another path containing compiler headers --- bin/app/data/fallback/ApplicationSettings.xml | 2 +- src/app/main.cpp | 2 + src/lib/settings/ApplicationSettings.cpp | 6 +- src/lib/utility/ResourcePaths.cpp | 2 +- src/lib/utility/utilityCxx.cpp | 17 +-- .../data/indexer/IndexerCommandCxx.cpp | 28 +++-- src/lib_gui/qt/element/QtPathListBox.cpp | 4 + src/lib_gui/qt/element/QtPathListBox.h | 2 + .../QtProjectWizzardContentPaths.cpp | 100 +++++++++++++++++- .../QtProjectWizzardContentPaths.h | 14 ++- .../cxx_header/CxxHeaderPathDetector.cpp | 9 +- .../CxxVs10To14HeaderPathDetector.cpp | 1 - .../cxx_header/CxxVs15HeaderPathDetector.cpp | 1 - 13 files changed, 153 insertions(+), 35 deletions(-) diff --git a/bin/app/data/fallback/ApplicationSettings.xml b/bin/app/data/fallback/ApplicationSettings.xml index e2685652..10367d1d 100644 --- a/bin/app/data/fallback/ApplicationSettings.xml +++ b/bin/app/data/fallback/ApplicationSettings.xml @@ -14,5 +14,5 @@ ./projects/javaparser/javaparser.srctrlprj - 5 + 6 diff --git a/src/app/main.cpp b/src/app/main.cpp index 62059f4e..3f16a1eb 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -137,6 +137,8 @@ void prefillCxxHeaderPaths() std::shared_ptr cxxHeaderDetector = utility::getCxxHeaderPathDetector(); std::vector paths = cxxHeaderDetector->getPaths(); + paths = utility::replaceOrAddCxxCompilerHeaderPath(paths); + if (!paths.empty()) { MessageStatus(L"Ran C/C++ header path detection, found " + std::to_wstring(paths.size()) + L" path" + diff --git a/src/lib/settings/ApplicationSettings.cpp b/src/lib/settings/ApplicationSettings.cpp index 8ebe06a3..e1d543e3 100644 --- a/src/lib/settings/ApplicationSettings.cpp +++ b/src/lib/settings/ApplicationSettings.cpp @@ -13,7 +13,7 @@ #include "UserPaths.h" #include "Version.h" -const size_t ApplicationSettings::VERSION = 5; +const size_t ApplicationSettings::VERSION = 6; std::shared_ptr ApplicationSettings::s_instance; @@ -78,11 +78,11 @@ bool ApplicationSettings::load(const FilePath& filePath, bool readOnly) } } )); - migrator.addMigration(5, std::make_shared( + migrator.addMigration(6, std::make_shared( [](const SettingsMigration* migration, Settings* settings) { std::vector cxxHeaderSearchPaths = migration->getValuesFromSettings( - settings, "indexing/cxx/header_search_paths/header_search_path", std::vector()); + settings, "indexing/cxx/header_search_paths/header_search_path", std::vector()); cxxHeaderSearchPaths = utility::replaceOrAddCxxCompilerHeaderPath(cxxHeaderSearchPaths); diff --git a/src/lib/utility/ResourcePaths.cpp b/src/lib/utility/ResourcePaths.cpp index adfc6376..b61c4438 100644 --- a/src/lib/utility/ResourcePaths.cpp +++ b/src/lib/utility/ResourcePaths.cpp @@ -34,5 +34,5 @@ FilePath ResourcePaths::getJavaPath() FilePath ResourcePaths::getCxxCompilerHeaderPath() { - return AppPath::getAppPath().concatenate(L"data/cxx/include/"); + return AppPath::getAppPath().concatenate(L"data/cxx/include/").getCanonical(); } diff --git a/src/lib/utility/utilityCxx.cpp b/src/lib/utility/utilityCxx.cpp index ac9b0ea5..1a28b362 100644 --- a/src/lib/utility/utilityCxx.cpp +++ b/src/lib/utility/utilityCxx.cpp @@ -1,30 +1,23 @@ #include "utilityCxx.h" #include "ResourcePaths.h" -#include "utilityApp.h" namespace utility { std::vector replaceOrAddCxxCompilerHeaderPath(const std::vector& headerSearchPaths) { std::vector newHeaderSearchPaths; + const FilePath cxxCompilerHeaderPath = ResourcePaths::getCxxCompilerHeaderPath(); - if (utility::getOsType() == OS_WINDOWS) + for (const FilePath& path : headerSearchPaths) { - newHeaderSearchPaths = headerSearchPaths; - } - else - { - for (const FilePath& path : headerSearchPaths) + if (path != cxxCompilerHeaderPath) { - if (!path.getConcatenated(L"/stdarg.h").exists()) - { - newHeaderSearchPaths.push_back(path); - } + newHeaderSearchPaths.push_back(path); } } - newHeaderSearchPaths.push_back(ResourcePaths::getCxxCompilerHeaderPath().getCanonical()); + newHeaderSearchPaths.push_back(cxxCompilerHeaderPath); return newHeaderSearchPaths; } } diff --git a/src/lib_cxx/data/indexer/IndexerCommandCxx.cpp b/src/lib_cxx/data/indexer/IndexerCommandCxx.cpp index a944c3bc..89c890fb 100644 --- a/src/lib_cxx/data/indexer/IndexerCommandCxx.cpp +++ b/src/lib_cxx/data/indexer/IndexerCommandCxx.cpp @@ -60,19 +60,33 @@ std::vector IndexerCommandCxx::getCompilerFlagsForSystemHeaderSear { std::vector compilerFlags; compilerFlags.reserve(systemHeaderSearchPaths.size() * 2); + + bool hasCxxCompilerHeaderPath = false; for (const FilePath& path : systemHeaderSearchPaths) + { + if (path == ResourcePaths::getCxxCompilerHeaderPath()) + { + hasCxxCompilerHeaderPath = true; + } + else + { + compilerFlags.push_back(L"-isystem"); + compilerFlags.push_back(path.wstr()); + } + } + + if (hasCxxCompilerHeaderPath) { #ifdef _WIN32 // prepend clang system includes on windows - if (path == ResourcePaths::getCxxCompilerHeaderPath()) - { - compilerFlags = utility::concat({ L"-isystem" , path.wstr() }, compilerFlags); - continue; - } -#endif + compilerFlags = utility::concat({ L"-isystem", ResourcePaths::getCxxCompilerHeaderPath().wstr() }, compilerFlags); +#else + // append otherwise compilerFlags.push_back(L"-isystem"); - compilerFlags.push_back(path.wstr()); + compilerFlags.push_back(ResourcePaths::getCxxCompilerHeaderPath().wstr()); +#endif } + return compilerFlags; } diff --git a/src/lib_gui/qt/element/QtPathListBox.cpp b/src/lib_gui/qt/element/QtPathListBox.cpp index 43ae1177..581dc0dc 100644 --- a/src/lib_gui/qt/element/QtPathListBox.cpp +++ b/src/lib_gui/qt/element/QtPathListBox.cpp @@ -59,7 +59,11 @@ std::vector QtPathListBox::getPathsAsAbsolute() const void QtPathListBox::setPaths(const std::vector& list, bool readOnly) { clear(); + addPaths(list, readOnly); +} +void QtPathListBox::addPaths(const std::vector& list, bool readOnly) +{ for (FilePath path : list) { QtListBoxItem* item = addListBoxItemWithText(QString::fromStdWString(path.wstr())); diff --git a/src/lib_gui/qt/element/QtPathListBox.h b/src/lib_gui/qt/element/QtPathListBox.h index 400d3b3d..035b89cd 100644 --- a/src/lib_gui/qt/element/QtPathListBox.h +++ b/src/lib_gui/qt/element/QtPathListBox.h @@ -23,7 +23,9 @@ public: std::vector getPathsAsDisplayed() const; std::vector getPathsAsAbsolute() const; + void setPaths(const std::vector& list, bool readOnly = false); + void addPaths(const std::vector& list, bool readOnly = false); void makeAbsolute(FilePath& path) const; void makeRelativeIfShorter(FilePath& path) const; diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp index fee47ec2..8bf53bf9 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp @@ -15,6 +15,7 @@ #include "SourceGroupCxxEmpty.h" #include "SourceGroupJavaEmpty.h" #include "ApplicationSettings.h" +#include "ResourcePaths.h" #include "SourceGroupSettingsCustomCommand.h" #include "SourceGroupSettingsCxx.h" #include "SourceGroupSettingsCxxCdb.h" @@ -34,6 +35,7 @@ #include "IncludeProcessing.h" #include "ScopedFunctor.h" #include "utility.h" +#include "utilityApp.h" #include "utilityCxx.h" #include "utilityFile.h" #include "utilityPathDetection.h" @@ -204,6 +206,11 @@ void QtProjectWizzardContentPaths::detectionClicked() paths = utility::unique(utility::concat(oldPaths, paths)); + detectedPaths(paths); +} + +void QtProjectWizzardContentPaths::detectedPaths(const std::vector& paths) +{ m_list->setPaths(paths); } @@ -1011,7 +1018,7 @@ QtProjectWizzardContentPathsHeaderSearchGlobal::QtProjectWizzardContentPathsHead void QtProjectWizzardContentPathsHeaderSearchGlobal::load() { - m_list->setPaths(ApplicationSettings::getInstance()->getHeaderSearchPaths()); + setPaths(ApplicationSettings::getInstance()->getHeaderSearchPaths()); } void QtProjectWizzardContentPathsHeaderSearchGlobal::save() @@ -1020,6 +1027,97 @@ void QtProjectWizzardContentPathsHeaderSearchGlobal::save() ApplicationSettings::getInstance()->save(); } +bool QtProjectWizzardContentPathsHeaderSearchGlobal::check() +{ + bool hasCompilerHeaderPath = false; + bool hasOtherCompilerConfig = false; + for (const FilePath& headerPath : m_list->getPathsAsDisplayed()) + { + if (headerPath == ResourcePaths::getCxxCompilerHeaderPath()) + { + hasCompilerHeaderPath = true; + } + else if (headerPath.getCanonical().getConcatenated(L"/stdarg.h").exists()) + { + hasOtherCompilerConfig = true; + } + } + + if (!hasCompilerHeaderPath) + { + QMessageBox msgBox; + msgBox.setText("Compiler Header Path missing"); + msgBox.setInformativeText("Your Global Include Paths do not contain the path to the compiler headers of " + "Sourcetrail's C/C++ indexer. This can cause a lot of errors during indexing. Do you want to add the " + "path to the list?"); + msgBox.addButton("Add", QMessageBox::ButtonRole::YesRole); + msgBox.addButton("Skip", QMessageBox::ButtonRole::NoRole); + msgBox.setIcon(QMessageBox::Icon::Question); + int ret = msgBox.exec(); + + if (ret == 0) // QMessageBox::Yes + { + m_list->addPaths({ ResourcePaths::getCxxCompilerHeaderPath() }, true); + hasCompilerHeaderPath = true; + } + } + + if (utility::getOsType() != OS_WINDOWS && hasOtherCompilerConfig && hasCompilerHeaderPath) + { + QMessageBox msgBox; + msgBox.setText("Multiple Compiler Headers"); + msgBox.setInformativeText("Your Global Include Paths contain another path that holds C/C++ compiler headers, " + "probably those of your local C/C++ compiler. They are possibly in conflict with the compiler headers of " + "Sourcetrail's C/C++ indexer. This can lead to compatiblity errors during indexing. Do you want to remove " + "these paths?"); + msgBox.addButton("Remove", QMessageBox::ButtonRole::YesRole); + msgBox.addButton("Keep", QMessageBox::ButtonRole::NoRole); + msgBox.setIcon(QMessageBox::Icon::Question); + int ret = msgBox.exec(); + + if (ret == 0) // QMessageBox::Yes + { + std::vector paths; + for (const FilePath& headerPath : m_list->getPathsAsDisplayed()) + { + if (headerPath == ResourcePaths::getCxxCompilerHeaderPath() || + !headerPath.getCanonical().getConcatenated(L"/stdarg.h").exists()) + { + paths.push_back(headerPath); + } + } + setPaths(paths); + } + } + + return QtProjectWizzardContentPaths::check(); +} + +void QtProjectWizzardContentPathsHeaderSearchGlobal::detectedPaths(const std::vector& paths) +{ + setPaths(paths); +} + +void QtProjectWizzardContentPathsHeaderSearchGlobal::setPaths(const std::vector& paths) +{ + m_list->setPaths({}); + + std::vector nonCxxCompilerHeaderPaths; + for (const FilePath& headerPath : paths) + { + if (headerPath == ResourcePaths::getCxxCompilerHeaderPath()) + { + m_list->addPaths({ headerPath }, true); + } + else + { + nonCxxCompilerHeaderPaths.push_back(headerPath); + } + } + + m_list->addPaths(nonCxxCompilerHeaderPaths); +} + QtProjectWizzardContentPathsFrameworkSearch::QtProjectWizzardContentPathsFrameworkSearch( std::shared_ptr settings, QtProjectWizzardWindow* window, bool indicateAsAdditional diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h index 31c124b0..a020ac0f 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h @@ -27,8 +27,8 @@ signals: public: QtProjectWizzardContentPaths( - std::shared_ptr settings, - QtProjectWizzardWindow* window, + std::shared_ptr settings, + QtProjectWizzardWindow* window, QtPathListBox::SelectionPolicyType selectionPolicy, bool checkMissingPaths = true); @@ -43,6 +43,8 @@ protected: void addDetection(QGridLayout* layout, int row); + virtual void detectedPaths(const std::vector& paths); + std::shared_ptr m_settings; QtPathListBox* m_list; @@ -166,6 +168,14 @@ public: // QtProjectWizzardContent implementation virtual void load() override; virtual void save() override; + + virtual bool check() override; + +protected: + virtual void detectedPaths(const std::vector& paths) override; + +private: + void setPaths(const std::vector& paths); }; diff --git a/src/lib_gui/utility/path_detector/cxx_header/CxxHeaderPathDetector.cpp b/src/lib_gui/utility/path_detector/cxx_header/CxxHeaderPathDetector.cpp index 22b09900..46af08fe 100644 --- a/src/lib_gui/utility/path_detector/cxx_header/CxxHeaderPathDetector.cpp +++ b/src/lib_gui/utility/path_detector/cxx_header/CxxHeaderPathDetector.cpp @@ -15,18 +15,15 @@ std::vector CxxHeaderPathDetector::getPaths() const { std::vector paths = utility::getCxxHeaderPaths(m_compilerName); std::vector headerSearchPaths; + for (const std::string& path : paths) { - if (!utility::isPostfix(" (framework directory)", path)) + if (!utility::isPostfix(" (framework directory)", path) && + !FilePath(path).getCanonical().getConcatenated(L"/stdarg.h").exists()) { headerSearchPaths.push_back(FilePath(path).makeCanonical()); } } - if (!headerSearchPaths.empty()) - { - headerSearchPaths = utility::replaceOrAddCxxCompilerHeaderPath(headerSearchPaths); - } - return headerSearchPaths; } diff --git a/src/lib_gui/utility/path_detector/cxx_header/CxxVs10To14HeaderPathDetector.cpp b/src/lib_gui/utility/path_detector/cxx_header/CxxVs10To14HeaderPathDetector.cpp index bf779fa1..9ad94b5d 100644 --- a/src/lib_gui/utility/path_detector/cxx_header/CxxVs10To14HeaderPathDetector.cpp +++ b/src/lib_gui/utility/path_detector/cxx_header/CxxVs10To14HeaderPathDetector.cpp @@ -39,7 +39,6 @@ std::vector CxxVs10To14HeaderPathDetector::getPaths() const if (!headerSearchPaths.empty()) { utility::append(headerSearchPaths, utility::getWindowsSdkHeaderSearchPaths(m_architecture)); - headerSearchPaths = utility::replaceOrAddCxxCompilerHeaderPath(headerSearchPaths); } return headerSearchPaths; diff --git a/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp b/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp index 20a5d293..5073c3bd 100644 --- a/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp +++ b/src/lib_gui/utility/path_detector/cxx_header/CxxVs15HeaderPathDetector.cpp @@ -51,7 +51,6 @@ std::vector CxxVs15HeaderPathDetector::getPaths() const windowsSdkHeaderSearchPaths = utility::getWindowsSdkHeaderSearchPaths(APPLICATION_ARCHITECTURE_X86_64); } utility::append(headerSearchPaths, windowsSdkHeaderSearchPaths); - headerSearchPaths = utility::replaceOrAddCxxCompilerHeaderPath(headerSearchPaths); } return headerSearchPaths;