#include "ProjectSettings.h" #include "SettingsMigrationDeleteKey.h" #include "SettingsMigrationLambda.h" #include "SettingsMigrationMoveKey.h" #include "SourceGroupSettingsCustomCommand.h" #include "SourceGroupSettingsUnloadable.h" #include "logging.h" #include "utilityFile.h" #include "utilityString.h" #include "utilityUuid.h" #if BUILD_CXX_LANGUAGE_PACKAGE #include "SourceGroupSettingsCEmpty.h" #include "SourceGroupSettingsCppEmpty.h" #include "SourceGroupSettingsCxxCdb.h" #include "SourceGroupSettingsCxxCodeblocks.h" #endif // BUILD_CXX_LANGUAGE_PACKAGE #if BUILD_JAVA_LANGUAGE_PACKAGE #include "SourceGroupSettingsJavaEmpty.h" #include "SourceGroupSettingsJavaMaven.h" #include "SourceGroupSettingsJavaGradle.h" #endif // BUILD_JAVA_LANGUAGE_PACKAGE #if BUILD_PYTHON_LANGUAGE_PACKAGE #include "SourceGroupSettingsPythonEmpty.h" #endif // BUILD_PYTHON_LANGUAGE_PACKAGE const std::wstring ProjectSettings::PROJECT_FILE_EXTENSION = L".srctrlprj"; const std::wstring ProjectSettings::BOOKMARK_DB_FILE_EXTENSION = L".srctrlbm"; const std::wstring ProjectSettings::INDEX_DB_FILE_EXTENSION = L".srctrldb"; const std::wstring ProjectSettings::TEMP_INDEX_DB_FILE_EXTENSION = L".srctrldb_tmp"; const size_t ProjectSettings::VERSION = 8; LanguageType ProjectSettings::getLanguageOfProject(const FilePath& filePath) { LanguageType languageType = LANGUAGE_UNKNOWN; ProjectSettings projectSettings; projectSettings.load(filePath); for (const std::shared_ptr& sourceGroupSettings: projectSettings.getAllSourceGroupSettings()) { const LanguageType currentLanguageType = getLanguageTypeForSourceGroupType(sourceGroupSettings->getType()); if (languageType == LANGUAGE_UNKNOWN) { languageType = currentLanguageType; } else if (languageType != currentLanguageType) { // language is unknown if source groups have different languages. languageType = LANGUAGE_UNKNOWN; break; } } return languageType; } ProjectSettings::ProjectSettings() { } ProjectSettings::ProjectSettings(const FilePath& projectFilePath) { setFilePath(projectFilePath); } ProjectSettings::~ProjectSettings() { } bool ProjectSettings::equalsExceptNameAndLocation(const ProjectSettings& other) const { const std::vector> allMySettings = getAllSourceGroupSettings(); const std::vector> allOtherSettings = other.getAllSourceGroupSettings(); if (allMySettings.size() != allOtherSettings.size()) { return false; } for (const std::shared_ptr& mySourceGroup : allMySettings) { bool matched = false; for (const std::shared_ptr& otherSourceGroup : allOtherSettings) { if (mySourceGroup->equalsSettings(otherSourceGroup.get())) { matched = true; break; } } if (!matched) { return false; } } return true; } bool ProjectSettings::needMigration() const { if (getVersion() == 0) { return false; } return getMigrations().willMigrate(this, ProjectSettings::VERSION); } void ProjectSettings::migrate() { SettingsMigrator migrator = getMigrations(); bool migrated = migrator.migrate(this, ProjectSettings::VERSION); if (migrated) { save(); } } bool ProjectSettings::reload() { return Settings::load(getFilePath()); } FilePath ProjectSettings::getProjectFilePath() const { return getFilePath(); } void ProjectSettings::setProjectFilePath(std::wstring projectName, const FilePath& projectFileLocation) { setFilePath(projectFileLocation.getConcatenated(L"/" + projectName + PROJECT_FILE_EXTENSION)); } FilePath ProjectSettings::getDependenciesDirectoryPath() const { return getProjectDirectoryPath().concatenate(L"sourcetrail_dependencies"); } FilePath ProjectSettings::getDBFilePath() const { return getFilePath().replaceExtension(INDEX_DB_FILE_EXTENSION); } FilePath ProjectSettings::getTempDBFilePath() const { return getFilePath().replaceExtension(TEMP_INDEX_DB_FILE_EXTENSION); } FilePath ProjectSettings::getBookmarkDBFilePath() const { return getFilePath().replaceExtension(BOOKMARK_DB_FILE_EXTENSION); } std::wstring ProjectSettings::getProjectName() const { return getFilePath().withoutExtension().fileName(); } FilePath ProjectSettings::getProjectDirectoryPath() const { return getFilePath().getParentDirectory(); } std::string ProjectSettings::getDescription() const { return getValue("description", ""); } std::vector> ProjectSettings::getAllSourceGroupSettings() const { std::vector> allSettings; for (const std::string& key: m_config->getSublevelKeys("source_groups")) { const std::string id = key.substr(std::string(SourceGroupSettings::s_keyPrefix).length()); const SourceGroupType type = stringToSourceGroupType(getValue(key + "/type", "")); std::shared_ptr settings; switch (type) { #if BUILD_CXX_LANGUAGE_PACKAGE case SOURCE_GROUP_C_EMPTY: settings = std::make_shared(id, this); break; case SOURCE_GROUP_CPP_EMPTY: settings = std::make_shared(id, this); break; case SOURCE_GROUP_CXX_CDB: settings = std::make_shared(id, this); break; case SOURCE_GROUP_CXX_CODEBLOCKS: settings = std::make_shared(id, this); break; #endif // BUILD_CXX_LANGUAGE_PACKAGE #if BUILD_JAVA_LANGUAGE_PACKAGE case SOURCE_GROUP_JAVA_EMPTY: settings = std::make_shared(id, this); break; case SOURCE_GROUP_JAVA_MAVEN: settings = std::make_shared(id, this); break; case SOURCE_GROUP_JAVA_GRADLE: settings = std::make_shared(id, this); break; #endif // BUILD_JAVA_LANGUAGE_PACKAGE #if BUILD_PYTHON_LANGUAGE_PACKAGE case SOURCE_GROUP_PYTHON_EMPTY: settings = std::make_shared(id, this); break; #endif // BUILD_PYTHON_LANGUAGE_PACKAGE case SOURCE_GROUP_CUSTOM_COMMAND: settings = std::make_shared(id, this); break; default: settings = std::make_shared(id, this); } if (settings) { settings->loadSettings(m_config.get()); allSettings.push_back(settings); } else { LOG_WARNING("Sourcegroup with id \"" + id + "\" could not be loaded."); } } return allSettings; } void ProjectSettings::setAllSourceGroupSettings(const std::vector>& allSettings) { for (const std::string& key: m_config->getSublevelKeys("source_groups")) { m_config->removeValues(key); } for (const std::shared_ptr& settings: allSettings) { const std::string key = SourceGroupSettings::s_keyPrefix + settings->getId(); const SourceGroupType type = settings->getType(); setValue(key + "/type", sourceGroupTypeToString(type)); settings->saveSettings(m_config.get()); } } std::vector ProjectSettings::makePathsExpandedAndAbsolute(const std::vector& paths) const { std::vector p = utility::getExpandedPaths(paths); std::vector absPaths; const FilePath basePath = getProjectDirectoryPath(); for (const FilePath& path : p) { if (path.isAbsolute()) { absPaths.push_back(path); } else { absPaths.push_back(basePath.getConcatenated(path).makeCanonical()); } } return absPaths; } FilePath ProjectSettings::makePathExpandedAndAbsolute(const FilePath& path) const { return utility::getExpandedAndAbsolutePath(path, getProjectDirectoryPath()); } SettingsMigrator ProjectSettings::getMigrations() const { SettingsMigrator migrator; migrator.addMigration(1, std::make_shared( [](const SettingsMigration* migration, Settings* settings) { const std::string language = migration->getValueFromSettings(settings, "language_settings/language", ""); const std::string standard = migration->getValueFromSettings(settings, "language_settings/standard", ""); if (language == "C" && !utility::isPrefix("c", standard)) { migration->setValueInSettings(settings, "language_settings/standard", "c" + standard); } if (language == "C++" && !utility::isPrefix("c++", standard)) { migration->setValueInSettings(settings, "language_settings/standard", "c++" + standard); } } )); { const std::string sourceGroupKey = "source_groups/source_group_" + utility::getUuidString(); migrator.addMigration(2, std::make_shared("info/description", "description")); migrator.addMigration(2, std::make_shared("language_settings/standard", sourceGroupKey + "/standard")); migrator.addMigration(2, std::make_shared("source/source_paths/source_path", sourceGroupKey + "/source_paths/source_path")); migrator.addMigration(2, std::make_shared("source/exclude_paths/exclude_path", sourceGroupKey + "/exclude_paths/exclude_path")); migrator.addMigration(2, std::make_shared("source/extensions/source_extensions", sourceGroupKey + "/source_extensions/source_extension")); migrator.addMigration(2, std::make_shared("source/header_search_paths/header_search_path", sourceGroupKey + "/header_search_paths/header_search_path")); migrator.addMigration(2, std::make_shared("source/use_source_paths_for_header_search", sourceGroupKey + "/use_source_paths_for_header_search")); migrator.addMigration(2, std::make_shared("source/framework_search_paths/framework_search_path", sourceGroupKey + "/framework_search_paths/framework_search_path")); migrator.addMigration(2, std::make_shared("source/compiler_flags/compiler_flag", sourceGroupKey + "/compiler_flags/compiler_flag")); migrator.addMigration(2, std::make_shared("source/build_file_path/compilation_db_path", sourceGroupKey + "/build_file_path/compilation_db_path")); migrator.addMigration(2, std::make_shared("source/class_paths/class_path", sourceGroupKey + "/class_paths/class_path")); migrator.addMigration(2, std::make_shared("source/maven/project_file_path", sourceGroupKey + "/maven/project_file_path")); migrator.addMigration(2, std::make_shared("source/maven/dependencies_directory", sourceGroupKey + "/maven/dependencies_directory")); migrator.addMigration(2, std::make_shared("source/maven/should_index_tests", sourceGroupKey + "/maven/should_index_tests")); migrator.addMigration(3, std::make_shared( [=](const SettingsMigration* migration, Settings* settings) { const std::string language = migration->getValueFromSettings(settings, "language_settings/language", ""); SourceGroupType type = SOURCE_GROUP_UNKNOWN; #if BUILD_CXX_LANGUAGE_PACKAGE if (language == "C" || language == "C++") { const std::string cdbPath = migration->getValueFromSettings(settings, sourceGroupKey + "/build_file_path/compilation_db_path", ""); if (!cdbPath.empty()) { type = SOURCE_GROUP_CXX_CDB; } else if (language == "C") { type = SOURCE_GROUP_C_EMPTY; } else { type = SOURCE_GROUP_CPP_EMPTY; } } #endif // BUILD_CXX_LANGUAGE_PACKAGE #if BUILD_JAVA_LANGUAGE_PACKAGE if (language == "Java") { const std::string mavenProjectFilePath = migration->getValueFromSettings(settings, sourceGroupKey + "/maven/project_file_path", ""); if (!mavenProjectFilePath.empty()) { type = SOURCE_GROUP_JAVA_MAVEN; } const std::string gradleProjectFilePath = migration->getValueFromSettings(settings, sourceGroupKey + "/gradle/project_file_path", ""); if (!gradleProjectFilePath.empty()) { type = SOURCE_GROUP_JAVA_GRADLE; } else { type = SOURCE_GROUP_JAVA_EMPTY; } } #endif // BUILD_JAVA_LANGUAGE_PACKAGE migration->setValueInSettings(settings, sourceGroupKey + "/type", sourceGroupTypeToString(type)); } )); } migrator.addMigration(4, std::make_shared("language_settings/language")); migrator.addMigration(4, std::make_shared("source/build_file_path/vs_solution_path")); migrator.addMigration(4, std::make_shared("source/extensions/header_extensions")); for (std::shared_ptr sourceGroupSettings : getAllSourceGroupSettings()) { const std::string key = SourceGroupSettings::s_keyPrefix + sourceGroupSettings->getId(); migrator.addMigration(5, std::make_shared(key + "/exclude_paths/exclude_path", key + "/exclude_filters/exclude_filter")); } for (std::shared_ptr sourceGroupSettings : getAllSourceGroupSettings()) { #if BUILD_CXX_LANGUAGE_PACKAGE 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")); } #endif // BUILD_CXX_LANGUAGE_PACKAGE } for (std::shared_ptr sourceGroupSettings : getAllSourceGroupSettings()) { std::string languageName; switch (getLanguageTypeForSourceGroupType(sourceGroupSettings->getType())) { #if BUILD_CXX_LANGUAGE_PACKAGE case LANGUAGE_C: languageName = "c"; break; case LANGUAGE_CPP: languageName = "cpp"; break; #endif // BUILD_CXX_LANGUAGE_PACKAGE #if BUILD_JAVA_LANGUAGE_PACKAGE case LANGUAGE_JAVA: languageName = "java"; break; #endif // BUILD_JAVA_LANGUAGE_PACKAGE default: continue; } std::string key = SourceGroupSettings::s_keyPrefix + sourceGroupSettings->getId(); migrator.addMigration(7, std::make_shared(key + "/standard", key + "/" + languageName + "_standard")); } for (std::shared_ptr sourceGroupSettings : getAllSourceGroupSettings()) { const std::string key = SourceGroupSettings::s_keyPrefix + sourceGroupSettings->getId(); migrator.addMigration(8, std::make_shared(key + "/python_environment_directory_path", key + "/python_environment_path")); } return migrator; }