diff --git a/src/lib/project/SourceGroup.h b/src/lib/project/SourceGroup.h index 6f1b8164..765eb87e 100644 --- a/src/lib/project/SourceGroup.h +++ b/src/lib/project/SourceGroup.h @@ -26,7 +26,7 @@ public: virtual bool prepareIndexing(); void fetchAllSourceFilePaths(); - std::set getIndexedPaths() const; + virtual std::set getIndexedPaths() const; std::set getExcludeFilters() const; std::set getAllSourceFilePaths() const; std::set getSourceFilePathsToIndex(const std::set& staticSourceFilePaths) const; @@ -35,12 +35,13 @@ public: std::set m_allSourceFilePaths; +protected: + std::set findAndAddSymlinkedDirectories(const std::vector& paths) const; + private: virtual std::shared_ptr getSourceGroupSettings() = 0; virtual std::shared_ptr getSourceGroupSettings() const = 0; virtual std::vector getAllSourcePaths() const = 0; - - std::set findAndAddSymlinkedDirectories(const std::vector& paths) const; }; #endif // SOURCE_GROUP_H diff --git a/src/lib/settings/ProjectSettings.cpp b/src/lib/settings/ProjectSettings.cpp index fa9b9a79..3f475eaf 100644 --- a/src/lib/settings/ProjectSettings.cpp +++ b/src/lib/settings/ProjectSettings.cpp @@ -12,7 +12,7 @@ #include "utility/utilityString.h" #include "utility/utilityUuid.h" -const size_t ProjectSettings::VERSION = 5; +const size_t ProjectSettings::VERSION = 6; const wchar_t PROJECT_FILE_EXTENSION[] = L".srctrlprj"; LanguageType ProjectSettings::getLanguageOfProject(const FilePath& filePath) @@ -320,6 +320,15 @@ SettingsMigrator ProjectSettings::getMigrations() const migrator.addMigration(5, std::make_shared(key + "/exclude_paths/exclude_path", key + "/exclude_filters/exclude_filter")); } + for (std::shared_ptr sourceGroupSettings : getAllSourceGroupSettings()) + { + if (sourceGroupSettings->getType() == SOURCE_GROUP_CXX_CDB) + { + const std::string key = SourceGroupSettings::s_keyPrefix + sourceGroupSettings->getId(); + migrator.addMigration(6, std::make_shared(key + "/source_paths/source_path", key + "/indexed_header_paths/indexed_header_path")); + } + } + return migrator; } diff --git a/src/lib/settings/SourceGroupSettingsCxxCdb.cpp b/src/lib/settings/SourceGroupSettingsCxxCdb.cpp index ae639871..dea2f967 100644 --- a/src/lib/settings/SourceGroupSettingsCxxCdb.cpp +++ b/src/lib/settings/SourceGroupSettingsCxxCdb.cpp @@ -20,6 +20,7 @@ void SourceGroupSettingsCxxCdb::load(std::shared_ptr config const std::string key = s_keyPrefix + getId(); setCompilationDatabasePath(FilePath(getValue(key + "/build_file_path/compilation_db_path", L"", config))); + setIndexedHeaderPaths(getPathValues(key + "/indexed_header_paths/indexed_header_path", config)); } void SourceGroupSettingsCxxCdb::save(std::shared_ptr config) @@ -29,6 +30,7 @@ void SourceGroupSettingsCxxCdb::save(std::shared_ptr config) const std::string key = s_keyPrefix + getId(); setValue(key + "/build_file_path/compilation_db_path", getCompilationDatabasePath().wstr(), config); + setPathValues(key + "/indexed_header_paths/indexed_header_path", getIndexedHeaderPaths(), config); } bool SourceGroupSettingsCxxCdb::equals(std::shared_ptr other) const @@ -56,3 +58,19 @@ void SourceGroupSettingsCxxCdb::setCompilationDatabasePath(const FilePath& compi { m_compilationDatabasePath = compilationDatabasePath; } + +std::vector SourceGroupSettingsCxxCdb::getIndexedHeaderPaths() const +{ + return m_indexedHeaderPaths; +} + +std::vector SourceGroupSettingsCxxCdb::getIndexedHeaderPathsExpandedAndAbsolute() const +{ + return m_projectSettings->makePathsExpandedAndAbsolute(getIndexedHeaderPaths()); +} + +void SourceGroupSettingsCxxCdb::setIndexedHeaderPaths(const std::vector& indexedHeaderPaths) +{ + m_indexedHeaderPaths = indexedHeaderPaths; +} + diff --git a/src/lib/settings/SourceGroupSettingsCxxCdb.h b/src/lib/settings/SourceGroupSettingsCxxCdb.h index 36549e8a..230cfc16 100644 --- a/src/lib/settings/SourceGroupSettingsCxxCdb.h +++ b/src/lib/settings/SourceGroupSettingsCxxCdb.h @@ -19,8 +19,13 @@ public: FilePath getCompilationDatabasePathExpandedAndAbsolute() const; void setCompilationDatabasePath(const FilePath& compilationDatabasePath); + std::vector getIndexedHeaderPaths() const; + std::vector getIndexedHeaderPathsExpandedAndAbsolute() const; + void setIndexedHeaderPaths(const std::vector& indexedHeaderPaths); + private: FilePath m_compilationDatabasePath; + std::vector m_indexedHeaderPaths; }; #endif // SOURCE_GROUP_SETTINGS_CXX_CDB_H diff --git a/src/lib_cxx/project/SourceGroupCxxCdb.cpp b/src/lib_cxx/project/SourceGroupCxxCdb.cpp index 893d2c0d..a854bfd6 100644 --- a/src/lib_cxx/project/SourceGroupCxxCdb.cpp +++ b/src/lib_cxx/project/SourceGroupCxxCdb.cpp @@ -45,6 +45,12 @@ bool SourceGroupCxxCdb::prepareIndexing() return true; } +std::set SourceGroupCxxCdb::getIndexedPaths() const +{ + return findAndAddSymlinkedDirectories(m_settings->getIndexedHeaderPathsExpandedAndAbsolute()); +} + + std::vector> SourceGroupCxxCdb::getIndexerCommands(const std::set& filesToIndex) const { std::shared_ptr appSettings = ApplicationSettings::getInstance(); diff --git a/src/lib_cxx/project/SourceGroupCxxCdb.h b/src/lib_cxx/project/SourceGroupCxxCdb.h index 84156d47..66be3a3c 100644 --- a/src/lib_cxx/project/SourceGroupCxxCdb.h +++ b/src/lib_cxx/project/SourceGroupCxxCdb.h @@ -18,6 +18,8 @@ public: virtual bool prepareIndexing() override; + virtual std::set getIndexedPaths() const override; + virtual std::vector> getIndexerCommands(const std::set& filesToIndex) const override; private: diff --git a/src/lib_cxx/utility/CompilationDatabase.cpp b/src/lib_cxx/utility/CompilationDatabase.cpp index 80264c38..432ac046 100644 --- a/src/lib_cxx/utility/CompilationDatabase.cpp +++ b/src/lib_cxx/utility/CompilationDatabase.cpp @@ -39,10 +39,16 @@ std::vector utility::CompilationDatabase::getFrameworkHeaderPaths() co void utility::CompilationDatabase::init() { std::string error; - std::shared_ptr cdb = std::shared_ptr( + std::shared_ptr cdb( clang::tooling::JSONCompilationDatabase::loadFromFile(utility::encodeToUtf8(m_filePath.wstr()), error, clang::tooling::JSONCommandLineSyntax::AutoDetect) ); + if (!cdb) + { + LOG_ERROR(L"Loading compilation database from file \"" + m_filePath.wstr() + L"\" failed with error: " + utility::decodeFromUtf8(error)); + return; + } + std::vector commands = cdb->getAllCompileCommands(); std::set frameworkHeaders; std::set systemHeaders; diff --git a/src/lib_gui/qt/window/QtSelectPathsDialog.cpp b/src/lib_gui/qt/window/QtSelectPathsDialog.cpp index 7f5680d4..b456509f 100644 --- a/src/lib_gui/qt/window/QtSelectPathsDialog.cpp +++ b/src/lib_gui/qt/window/QtSelectPathsDialog.cpp @@ -7,6 +7,7 @@ #include #include "utility/file/FilePath.h" +#include "utility/utility.h" QtSelectPathsDialog::QtSelectPathsDialog(const QString& title, const QString& description, QWidget* parent) : QtTextEditDialog(title, description, parent) @@ -28,11 +29,11 @@ std::vector QtSelectPathsDialog::getPathsList() const return checkedPaths; } -void QtSelectPathsDialog::setPathsList(const std::vector& paths, const std::vector& checkedPaths) +void QtSelectPathsDialog::setPathsList(const std::vector& paths, const std::vector& checkedPaths, const FilePath& rootPathForRelativePaths) { std::set checked(checkedPaths.begin(), checkedPaths.end()); - for (const FilePath& s : paths) + for (FilePath s : utility::unique(utility::concat(paths, checkedPaths))) { QListWidgetItem* item = new QListWidgetItem(QString::fromStdWString(s.wstr()), m_list); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag @@ -46,6 +47,11 @@ void QtSelectPathsDialog::setPathsList(const std::vector& paths, const item->setCheckState(Qt::Checked); } + if (!s.isAbsolute()) + { + s = rootPathForRelativePaths.getConcatenated(s); + } + if (!s.exists()) { item->setTextColor(Qt::red); diff --git a/src/lib_gui/qt/window/QtSelectPathsDialog.h b/src/lib_gui/qt/window/QtSelectPathsDialog.h index b7f429d4..49b155c1 100644 --- a/src/lib_gui/qt/window/QtSelectPathsDialog.h +++ b/src/lib_gui/qt/window/QtSelectPathsDialog.h @@ -14,7 +14,7 @@ public: QtSelectPathsDialog(const QString& title, const QString& description, QWidget* parent = 0); std::vector getPathsList() const; - void setPathsList(const std::vector& paths, const std::vector& checkedPaths); + void setPathsList(const std::vector& paths, const std::vector& checkedPaths, const FilePath& rootPathForRelativePaths); virtual void populateWindow(QWidget* widget) override; virtual void windowReady() override; diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp index 02ba2214..9377fc6e 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp @@ -9,6 +9,7 @@ #include "Application.h" #include "qt/element/QtLocationPicker.h" #include "qt/view/QtDialogView.h" +#include "qt/window/project_wizzard/QtProjectWizzardContentPaths.h" #include "settings/ApplicationSettings.h" #include "settings/SourceGroupSettingsCxxCdb.h" #include "settings/SourceGroupSettingsJavaMaven.h" @@ -164,6 +165,12 @@ void QtProjectWizzardContentPathCDB::save() void QtProjectWizzardContentPathCDB::pickedCDBPath() { m_window->saveContent(); + + if (std::shared_ptr cdbSettings = std::dynamic_pointer_cast(m_settings)) + { + cdbSettings->setIndexedHeaderPaths(QtProjectWizzardContentPathsCDBHeader::getIndexedPathsDerivedFromCDB(cdbSettings)); + } + m_window->loadContent(); } diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp index c3cf29e3..2298141a 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp @@ -253,25 +253,52 @@ QString QtProjectWizzardContentPathsSource::getFileNamesDescription() const } -std::vector QtProjectWizzardContentPathsCDBHeader::getTopLevelHeaderSearchPaths( +std::vector QtProjectWizzardContentPathsCDBHeader::getIndexedPathsDerivedFromCDB( std::shared_ptr settings) { + const FilePath projectPath = settings->getProjectDirectoryPath(); const FilePath cdbPath = settings->getCompilationDatabasePathExpandedAndAbsolute(); - if (!cdbPath.exists()) + + std::set indexedHeaderPaths; + if (!cdbPath.empty() && cdbPath.exists()) { - LOG_WARNING("Unable to fetch top level header search directories. The provided Compilation Database path does not exist."); - return std::vector(); + for (const FilePath& path : IndexerCommandCxxCdb::getSourceFilesFromCDB(cdbPath)) + { + indexedHeaderPaths.insert(path.getParentDirectory()); + } } - const std::vector sourcePaths = settings->getSourcePaths(); - return utility::getTopLevelPaths(utility::unique(utility::concat( - sourcePaths, utility::CompilationDatabase(cdbPath).getAllHeaderPaths() - ))); + else + { + LOG_WARNING("Unable to fetch indexed header paths. The provided Compilation Database path does not exist."); + } + + for (const FilePath& path : utility::CompilationDatabase(cdbPath).getAllHeaderPaths()) + { + if (path.exists() && projectPath.contains(path)) + { + indexedHeaderPaths.insert(path); + } + } + + std::vector rootPaths; + + FilePath lastPath; + for (const FilePath& path : indexedHeaderPaths) + { + if (lastPath.empty() || !lastPath.contains(path)) // don't add subdirectories of already added paths + { + lastPath = path; + rootPaths.push_back(path.getRelativeTo(projectPath)); + } + } + + return rootPaths; } QtProjectWizzardContentPathsCDBHeader::QtProjectWizzardContentPathsCDBHeader( std::shared_ptr settings, QtProjectWizzardWindow* window ) - : QtProjectWizzardContentPathsSource(settings, window) + : QtProjectWizzardContentPaths(settings, window, QtPathListBox::SELECTION_POLICY_FILES_AND_DIRECTORIES) { m_showFilesString = ""; @@ -305,47 +332,23 @@ void QtProjectWizzardContentPathsCDBHeader::populate(QGridLayout* layout, int& r void QtProjectWizzardContentPathsCDBHeader::load() { - if (m_settings->getSourcePaths().empty()) + if (std::shared_ptr cdbSettings = std::dynamic_pointer_cast(m_settings)) { - std::shared_ptr cdbSettings = - std::dynamic_pointer_cast(m_settings); - std::set sourcePaths; - - const FilePath projectPath = m_settings->getProjectDirectoryPath(); - const FilePath cdbPath = cdbSettings->getCompilationDatabasePathExpandedAndAbsolute(); - - if (!cdbPath.empty() && cdbPath.exists()) + if (cdbSettings->getIndexedHeaderPaths().empty()) { - for (const FilePath& path : IndexerCommandCxxCdb::getSourceFilesFromCDB(cdbPath)) - { - sourcePaths.insert(path.getParentDirectory()); - } + cdbSettings->setIndexedHeaderPaths(getIndexedPathsDerivedFromCDB(cdbSettings)); } - for (const FilePath& path : getTopLevelHeaderSearchPaths(cdbSettings)) - { - if (path.exists() && projectPath.contains(path)) - { - sourcePaths.insert(path); - } - } - - std::vector rootPaths; - - FilePath lastPath; - for (const FilePath& path : sourcePaths) - { - if (lastPath.empty() || !lastPath.contains(path)) // don't add subdirectories of already added paths - { - lastPath = path; - rootPaths.push_back(path.getRelativeTo(projectPath)); - } - } - - m_settings->setSourcePaths(rootPaths); + m_list->setPaths(cdbSettings->getIndexedHeaderPaths()); } +} - QtProjectWizzardContentPathsSource::load(); +void QtProjectWizzardContentPathsCDBHeader::save() +{ + if (std::shared_ptr cdbSettings = std::dynamic_pointer_cast(m_settings)) + { + cdbSettings->setIndexedHeaderPaths(m_list->getPathsAsDisplayed()); + } } bool QtProjectWizzardContentPathsCDBHeader::check() @@ -375,30 +378,33 @@ void QtProjectWizzardContentPathsCDBHeader::buttonClicked() if (!m_filesDialog) { - const FilePath cdbPath = - std::dynamic_pointer_cast(m_settings)->getCompilationDatabasePathExpandedAndAbsolute(); - if (!cdbPath.exists()) + if (std::shared_ptr cdbSettings = std::dynamic_pointer_cast(m_settings)) { - QMessageBox msgBox; - msgBox.setText("The provided Compilation Database path does not exist."); - msgBox.setDetailedText(QString::fromStdWString(cdbPath.wstr())); - msgBox.exec(); - return; + const FilePath cdbPath = cdbSettings->getCompilationDatabasePathExpandedAndAbsolute(); + if (!cdbPath.exists()) + { + QMessageBox msgBox; + msgBox.setText("The provided Compilation Database path does not exist."); + msgBox.setDetailedText(QString::fromStdWString(cdbPath.wstr())); + msgBox.exec(); + return; + } + + m_filesDialog = std::make_shared( + "Select from Include Paths", + "The list contains all Include Paths found in the Compilation Database. Red paths do not exist. Select the " + "paths containing the header files you want to index with Sourcetrail."); + m_filesDialog->setup(); + + connect(m_filesDialog.get(), &QtSelectPathsDialog::finished, this, &QtProjectWizzardContentPathsCDBHeader::savedFilesDialog); + connect(m_filesDialog.get(), &QtSelectPathsDialog::canceled, this, &QtProjectWizzardContentPathsCDBHeader::closedFilesDialog); + + dynamic_cast(m_filesDialog.get())->setPathsList( + getIndexedPathsDerivedFromCDB(cdbSettings), + cdbSettings->getIndexedHeaderPaths(), + m_settings->getProjectDirectoryPath() + ); } - - m_filesDialog = std::make_shared( - "Select from Include Paths", - "The list contains all Include Paths found in the Compilation Database. Red paths do not exist. Select the " - "paths containing the header files you want to index with Sourcetrail."); - m_filesDialog->setup(); - - connect(m_filesDialog.get(), &QtSelectPathsDialog::finished, this, &QtProjectWizzardContentPathsCDBHeader::savedFilesDialog); - connect(m_filesDialog.get(), &QtSelectPathsDialog::canceled, this, &QtProjectWizzardContentPathsCDBHeader::closedFilesDialog); - - dynamic_cast(m_filesDialog.get())->setPathsList( - getTopLevelHeaderSearchPaths(std::dynamic_pointer_cast(m_settings)), - m_settings->getSourcePaths() - ); } m_filesDialog->showWindow(); @@ -407,9 +413,7 @@ void QtProjectWizzardContentPathsCDBHeader::buttonClicked() void QtProjectWizzardContentPathsCDBHeader::savedFilesDialog() { - // TODO: extend instead of replace m_list->setPaths(dynamic_cast(m_filesDialog.get())->getPathsList()); - closedFilesDialog(); } diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h index a1377f50..4cedd958 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h @@ -79,19 +79,22 @@ public: virtual QString getFileNamesDescription() const override; }; + class QtProjectWizzardContentPathsCDBHeader - : public QtProjectWizzardContentPathsSource + : public QtProjectWizzardContentPaths { Q_OBJECT public: - static std::vector getTopLevelHeaderSearchPaths(std::shared_ptr settings); + static std::vector getIndexedPathsDerivedFromCDB(std::shared_ptr settings); QtProjectWizzardContentPathsCDBHeader(std::shared_ptr settings, QtProjectWizzardWindow* window); virtual void populate(QGridLayout* layout, int& row) override; + // QtProjectWizzardContent implementation virtual void load() override; + virtual void save() override; virtual bool check() override;