diff --git a/CMakeLists.txt b/CMakeLists.txt index 041dbe55..ef9bf75d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -518,6 +518,7 @@ set_property( PROPERTY INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/src/app" "${CMAKE_SOURCE_DIR}/src/lib" + "${CMAKE_SOURCE_DIR}/src/lib_utility" "${CMAKE_SOURCE_DIR}/src/lib_gui" "${CMAKE_SOURCE_DIR}/src/lib_license" "${CMAKE_SOURCE_DIR}/src/lib_cxx" diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index fd1eaac4..667ae801 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -352,6 +352,8 @@ add_files( utility/file/FileManager.h utility/file/FilePath.cpp utility/file/FilePath.h + utility/file/FilePathFilter.cpp + utility/file/FilePathFilter.h utility/file/FileRegister.cpp utility/file/FileRegister.h utility/file/FileRegisterStateData.cpp diff --git a/src/lib/data/indexer/IndexerCommand.cpp b/src/lib/data/indexer/IndexerCommand.cpp index 684c3e7e..aeb11517 100644 --- a/src/lib/data/indexer/IndexerCommand.cpp +++ b/src/lib/data/indexer/IndexerCommand.cpp @@ -3,11 +3,12 @@ #include "utility/utilityString.h" IndexerCommand::IndexerCommand( - const FilePath& sourceFilePath, const std::set& indexedPaths, const std::set& excludedPaths + const FilePath& sourceFilePath, const std::set& indexedPaths, + const std::set& excludeFilters ) : m_sourceFilePath(sourceFilePath) , m_indexedPaths(indexedPaths) - , m_excludedPaths(excludedPaths) + , m_excludeFilters(excludeFilters) { } @@ -24,9 +25,9 @@ size_t IndexerCommand::getByteSize(size_t stringSize) const size += stringSize + utility::encodeToUtf8(path.wstr()).size(); } - for (const FilePath& path : m_excludedPaths) + for (const FilePathFilter& filter : m_excludeFilters) { - size += stringSize + utility::encodeToUtf8(path.wstr()).size(); + size += stringSize + utility::encodeToUtf8(filter.wstr()).size(); } return size; @@ -42,7 +43,7 @@ const std::set& IndexerCommand::getIndexedPaths() const return m_indexedPaths; } -const std::set& IndexerCommand::getExcludedPath() const +const std::set& IndexerCommand::getExcludeFilters() const { - return m_excludedPaths; + return m_excludeFilters; } diff --git a/src/lib/data/indexer/IndexerCommand.h b/src/lib/data/indexer/IndexerCommand.h index e083c87f..a7c17abb 100644 --- a/src/lib/data/indexer/IndexerCommand.h +++ b/src/lib/data/indexer/IndexerCommand.h @@ -6,11 +6,12 @@ #include "data/indexer/IndexerCommandType.h" #include "utility/file/FilePath.h" +#include "utility/file/FilePathFilter.h" class IndexerCommand { public: - IndexerCommand(const FilePath& sourceFilePath, const std::set& indexedPaths, const std::set& excludedPaths); + IndexerCommand(const FilePath& sourceFilePath, const std::set& indexedPaths, const std::set& excludeFilters); virtual ~IndexerCommand(); virtual IndexerCommandType getIndexerCommandType() const = 0; @@ -19,12 +20,12 @@ public: const FilePath& getSourceFilePath() const; const std::set& getIndexedPaths() const; - const std::set& getExcludedPath() const; + const std::set& getExcludeFilters() const; private: FilePath m_sourceFilePath; std::set m_indexedPaths; - std::set m_excludedPaths; + std::set m_excludeFilters; }; #endif // INDEXER_COMMAND_H diff --git a/src/lib/data/indexer/interprocess/InterprocessIndexer.cpp b/src/lib/data/indexer/interprocess/InterprocessIndexer.cpp index 0ccb2777..75780d8e 100644 --- a/src/lib/data/indexer/interprocess/InterprocessIndexer.cpp +++ b/src/lib/data/indexer/interprocess/InterprocessIndexer.cpp @@ -54,7 +54,7 @@ void InterprocessIndexer::work() data.setIndexedFiles(m_interprocessIndexingStatusManager.getIndexedFiles()); std::shared_ptr fileRegister = std::make_shared( - data, indexerCommand->getSourceFilePath(), indexerCommand->getIndexedPaths(), indexerCommand->getExcludedPath() + data, indexerCommand->getSourceFilePath(), indexerCommand->getIndexedPaths(), indexerCommand->getExcludeFilters() ); LOG_INFO_STREAM(<< m_processId << " starting to index current file"); diff --git a/src/lib/data/indexer/interprocess/shared_types/SharedIndexerCommand.cpp b/src/lib/data/indexer/interprocess/shared_types/SharedIndexerCommand.cpp index 75fda395..39ad1c44 100644 --- a/src/lib/data/indexer/interprocess/shared_types/SharedIndexerCommand.cpp +++ b/src/lib/data/indexer/interprocess/shared_types/SharedIndexerCommand.cpp @@ -11,7 +11,7 @@ void SharedIndexerCommand::fromLocal(IndexerCommand* indexerCommand) { setSourceFilePath(indexerCommand->getSourceFilePath()); setIndexedPaths(indexerCommand->getIndexedPaths()); - setExcludedPaths(indexerCommand->getExcludedPath()); + setExcludeFilters(indexerCommand->getExcludeFilters()); if (dynamic_cast(indexerCommand) != nullptr) { @@ -58,7 +58,7 @@ std::shared_ptr SharedIndexerCommand::fromShared(const SharedInd std::shared_ptr command = std::make_shared( indexerCommand.getSourceFilePath(), indexerCommand.getIndexedPaths(), - indexerCommand.getExcludedPaths(), + indexerCommand.getExcludeFilters(), indexerCommand.getWorkingDirectory(), indexerCommand.getCompilerFlags(), indexerCommand.getSystemHeaderSearchPaths(), @@ -71,7 +71,7 @@ std::shared_ptr SharedIndexerCommand::fromShared(const SharedInd std::shared_ptr command = std::make_shared( indexerCommand.getSourceFilePath(), indexerCommand.getIndexedPaths(), - indexerCommand.getExcludedPaths(), + indexerCommand.getExcludeFilters(), indexerCommand.getWorkingDirectory(), indexerCommand.getLanguageStandard(), indexerCommand.getSystemHeaderSearchPaths(), @@ -85,7 +85,7 @@ std::shared_ptr SharedIndexerCommand::fromShared(const SharedInd return std::make_shared( indexerCommand.getSourceFilePath(), indexerCommand.getIndexedPaths(), - indexerCommand.getExcludedPaths(), + indexerCommand.getExcludeFilters(), indexerCommand.getLanguageStandard(), indexerCommand.getClassPaths() ); @@ -104,7 +104,7 @@ SharedIndexerCommand::SharedIndexerCommand(SharedMemory::Allocator* allocator) : m_type(Type::UNKNOWN) , m_sourceFilePath("", allocator) , m_indexedPaths(allocator) - , m_excludedPaths(allocator) + , m_excludeFilters(allocator) , m_workingDirectory("", allocator) , m_languageStandard("", allocator) , m_compilerFlags(allocator) @@ -152,27 +152,27 @@ void SharedIndexerCommand::setIndexedPaths(const std::set& indexedPath } } -std::set SharedIndexerCommand::getExcludedPaths() const +std::set SharedIndexerCommand::getExcludeFilters() const { - std::set result; + std::set result; - for (unsigned int i = 0; i < m_excludedPaths.size(); i++) + for (unsigned int i = 0; i < m_excludeFilters.size(); i++) { - result.insert(FilePath(utility::decodeFromUtf8(m_excludedPaths[i].c_str()))); + result.insert(FilePathFilter(utility::decodeFromUtf8(m_excludeFilters[i].c_str()))); } return result; } -void SharedIndexerCommand::setExcludedPaths(const std::set& excludedPaths) +void SharedIndexerCommand::setExcludeFilters(const std::set& excludeFilters) { - m_excludedPaths.clear(); + m_excludeFilters.clear(); - for (const FilePath& excludedPath : excludedPaths) + for (const FilePathFilter& excludeFilter : excludeFilters) { - SharedMemory::String path(m_excludedPaths.get_allocator()); - path = utility::encodeToUtf8(excludedPath.wstr()).c_str(); - m_excludedPaths.push_back(path); + SharedMemory::String path(m_excludeFilters.get_allocator()); + path = utility::encodeToUtf8(excludeFilter.wstr()).c_str(); + m_excludeFilters.push_back(path); } } diff --git a/src/lib/data/indexer/interprocess/shared_types/SharedIndexerCommand.h b/src/lib/data/indexer/interprocess/shared_types/SharedIndexerCommand.h index 06a455c6..dfc3c3ab 100644 --- a/src/lib/data/indexer/interprocess/shared_types/SharedIndexerCommand.h +++ b/src/lib/data/indexer/interprocess/shared_types/SharedIndexerCommand.h @@ -4,6 +4,7 @@ #include #include "utility/file/FilePath.h" +#include "utility/file/FilePathFilter.h" #include "utility/interprocess/SharedMemory.h" class IndexerCommand; @@ -23,8 +24,8 @@ public: std::set getIndexedPaths() const; void setIndexedPaths(const std::set& indexedPaths); - std::set getExcludedPaths() const; - void setExcludedPaths(const std::set& excludedPaths); + std::set getExcludeFilters() const; + void setExcludeFilters(const std::set& excludeFilters); FilePath getWorkingDirectory() const; void setWorkingDirectory(const FilePath& workingDirectory); @@ -61,7 +62,7 @@ private: // indexer command SharedMemory::String m_sourceFilePath; SharedMemory::Vector m_indexedPaths; - SharedMemory::Vector m_excludedPaths; + SharedMemory::Vector m_excludeFilters; // cxx SharedMemory::String m_workingDirectory; diff --git a/src/lib/project/SourceGroup.cpp b/src/lib/project/SourceGroup.cpp index c2d3680b..0ed21e4d 100644 --- a/src/lib/project/SourceGroup.cpp +++ b/src/lib/project/SourceGroup.cpp @@ -4,6 +4,7 @@ #include "utility/file/FileManager.h" #include "utility/file/FilePath.h" #include "utility/file/FileSystem.h" +#include "utility/utility.h" SourceGroup::~SourceGroup() { @@ -29,7 +30,7 @@ void SourceGroup::fetchAllSourceFilePaths() FileManager fileManager; fileManager.update( getAllSourcePaths(), - getSourceGroupSettings()->getExcludePathsExpandedAndAbsolute(), + getSourceGroupSettings()->getExcludeFiltersExpandedAndAbsolute(), getSourceGroupSettings()->getSourceExtensions() ); m_allSourceFilePaths = fileManager.getAllSourceFilePaths(); @@ -40,9 +41,9 @@ std::set SourceGroup::getIndexedPaths() const return findAndAddSymlinkedDirectories(getSourceGroupSettings()->getSourcePathsExpandedAndAbsolute()); } -std::set SourceGroup::getExcludedPaths() const +std::set SourceGroup::getExcludeFilters() const { - return findAndAddSymlinkedDirectories(getSourceGroupSettings()->getExcludePathsExpandedAndAbsolute()); + return utility::toSet(getSourceGroupSettings()->getExcludeFiltersExpandedAndAbsolute()); } std::set SourceGroup::getAllSourceFilePaths() const diff --git a/src/lib/project/SourceGroup.h b/src/lib/project/SourceGroup.h index d7ec8a34..6f1b8164 100644 --- a/src/lib/project/SourceGroup.h +++ b/src/lib/project/SourceGroup.h @@ -9,6 +9,7 @@ #include "settings/SourceGroupStatusType.h" #include "settings/SourceGroupType.h" #include "utility/file/FilePath.h" +#include "utility/file/FilePathFilter.h" class IndexerCommand; class SourceGroupSettings; @@ -26,7 +27,7 @@ public: void fetchAllSourceFilePaths(); std::set getIndexedPaths() const; - std::set getExcludedPaths() const; + std::set getExcludeFilters() const; std::set getAllSourceFilePaths() const; std::set getSourceFilePathsToIndex(const std::set& staticSourceFilePaths) const; diff --git a/src/lib/settings/ProjectSettings.cpp b/src/lib/settings/ProjectSettings.cpp index a2fc17a5..fa9b9a79 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 = 4; +const size_t ProjectSettings::VERSION = 5; const wchar_t PROJECT_FILE_EXTENSION[] = L".srctrlprj"; LanguageType ProjectSettings::getLanguageOfProject(const FilePath& filePath) @@ -248,71 +248,78 @@ SettingsMigrator ProjectSettings::getMigrations() const } )); - const std::string sourceGroupKey = "source_groups/source_group_" + utility::getUuidString(); + { + 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(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 (language == "C" || language == "C++") + migrator.addMigration(3, std::make_shared( + [=](const SettingsMigration* migration, Settings* settings) { - 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; - } - } - else 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; - } - } + const std::string language = migration->getValueFromSettings(settings, "language_settings/language", ""); - migration->setValueInSettings(settings, sourceGroupKey + "/type", sourceGroupTypeToString(type)); - } - )); + SourceGroupType type = SOURCE_GROUP_UNKNOWN; + 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; + } + } + else 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; + } + } + 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")); + } + return migrator; } diff --git a/src/lib/settings/Settings.cpp b/src/lib/settings/Settings.cpp index 71b53be0..b6699a45 100644 --- a/src/lib/settings/Settings.cpp +++ b/src/lib/settings/Settings.cpp @@ -85,9 +85,16 @@ void Settings::setVersion(size_t version) FilePath Settings::expandPath(const FilePath& path) { std::vector paths = path.expandEnvironmentVariables(); - if (paths.size() >= 1) + if (!paths.empty()) { - return paths[0]; + if (paths.size() > 1) + { + LOG_WARNING( + L"Environment variable in path \"" + path.wstr() + L"\" has been expanded to " + std::to_wstring(paths.size()) + + L"paths, but only \"" + paths.front().wstr() + L"\" will be used." + ); + } + return paths.front(); } return FilePath(); } diff --git a/src/lib/settings/SourceGroupSettings.cpp b/src/lib/settings/SourceGroupSettings.cpp index f9abed8a..6bcf1b59 100644 --- a/src/lib/settings/SourceGroupSettings.cpp +++ b/src/lib/settings/SourceGroupSettings.cpp @@ -1,8 +1,10 @@ #include "settings/SourceGroupSettings.h" +#include "utility/file/FileSystem.h" #include "utility/utility.h" -std::string SourceGroupSettings::s_keyPrefix = "source_groups/source_group_"; +const size_t SourceGroupSettings::s_version = 1; +const std::string SourceGroupSettings::s_keyPrefix = "source_groups/source_group_"; SourceGroupSettings::SourceGroupSettings(const std::string& id, SourceGroupType type, const ProjectSettings* projectSettings) : m_projectSettings(projectSettings) @@ -12,7 +14,7 @@ SourceGroupSettings::SourceGroupSettings(const std::string& id, SourceGroupType , m_status(SOURCE_GROUP_STATUS_ENABLED) , m_standard("") , m_sourcePaths(std::vector()) - , m_excludePaths(std::vector()) + , m_excludeFilters(std::vector()) , m_sourceExtensions(std::vector()) { } @@ -34,7 +36,7 @@ void SourceGroupSettings::load(std::shared_ptr config) setStatus(stringToSourceGroupStatusType(getValue(key + "/status", sourceGroupStatusTypeToString(SOURCE_GROUP_STATUS_ENABLED), config))); setStandard(getValue(key + "/standard", "", config)); setSourcePaths(getPathValues(key + "/source_paths/source_path", config)); - setExcludePaths(getPathValues(key + "/exclude_paths/exclude_path", config)); + setExcludeFilterStrings(getValues(key + "/exclude_filters/exclude_filter", std::vector(), config)); setSourceExtensions(getValues(key + "/source_extensions/source_extension", std::vector(), config)); } @@ -46,7 +48,7 @@ void SourceGroupSettings::save(std::shared_ptr config) setValue(key + "/name", getName(), config); setValue(key + "/standard", getStandard(), config); setPathValues(key + "/source_paths/source_path", getSourcePaths(), config); - setPathValues(key + "/exclude_paths/exclude_path", getExcludePaths(), config); + setValues(key + "/exclude_filters/exclude_filter", getExcludeFilterStrings(), config); setValues(key + "/source_extensions/source_extension", getSourceExtensions(), config); } @@ -59,7 +61,7 @@ bool SourceGroupSettings::equals(std::shared_ptr other) con m_status == other->m_status && m_standard == other->m_standard && utility::isPermutation(m_sourcePaths, other->m_sourcePaths) && - utility::isPermutation(m_excludePaths, other->m_excludePaths) && + utility::isPermutation(m_excludeFilters, other->m_excludeFilters) && utility::isPermutation(m_sourceExtensions, other->m_sourceExtensions) ); } @@ -143,19 +145,63 @@ void SourceGroupSettings::setSourcePaths(const std::vector& sourcePath m_sourcePaths = sourcePaths; } -std::vector SourceGroupSettings::getExcludePaths() const +std::vector SourceGroupSettings::getExcludeFilterStrings() const { - return m_excludePaths; + return m_excludeFilters; } -std::vector SourceGroupSettings::getExcludePathsExpandedAndAbsolute() const +std::vector SourceGroupSettings::getExcludeFiltersExpandedAndAbsolute() const { - return m_projectSettings->makePathsExpandedAndAbsolute(getExcludePaths()); + std::vector result; + + for (const FilePathFilter& filter : m_excludeFilters) + { + const std::wstring filterString = filter.wstr(); + const size_t wildcardPos = filterString.find(L"*"); + if (wildcardPos != filterString.npos) + { + std::wsmatch match; + if (std::regex_search(filterString, match, std::wregex(L"[\\\\/]")) && !match.empty() && match.position(0) < wildcardPos) + { + const FilePath p = m_projectSettings->makePathExpandedAndAbsolute(FilePath(match.prefix().str())); + std::set symLinkPaths = FileSystem::getSymLinkedDirectories(p); + symLinkPaths.insert(p); + + utility::append(result, + utility::convert( + utility::toVector(symLinkPaths), + [match](const FilePath& filePath) { return FilePathFilter(filePath.wstr() + L"/" + match.suffix().str()); } + ) + ); + } + else + { + result.push_back(filter); + } + } + else + { + const FilePath p = m_projectSettings->makePathExpandedAndAbsolute(FilePath(filterString)); + const bool isFile = p.exists() && !p.isDirectory(); + + std::set symLinkPaths = FileSystem::getSymLinkedDirectories(p); + symLinkPaths.insert(p); + + utility::append(result, + utility::convert( + utility::toVector(symLinkPaths), + [isFile](const FilePath& filePath) { return FilePathFilter(filePath.wstr() + (isFile ? L"" : L"**")); } + ) + ); + } + } + + return result; } -void SourceGroupSettings::setExcludePaths(const std::vector& excludePaths) +void SourceGroupSettings::setExcludeFilterStrings(const std::vector& excludeFilters) { - m_excludePaths = excludePaths; + m_excludeFilters = excludeFilters; } std::vector SourceGroupSettings::getSourceExtensions() const diff --git a/src/lib/settings/SourceGroupSettings.h b/src/lib/settings/SourceGroupSettings.h index 0744bd43..def3e733 100644 --- a/src/lib/settings/SourceGroupSettings.h +++ b/src/lib/settings/SourceGroupSettings.h @@ -7,13 +7,15 @@ #include "settings/ProjectSettings.h" #include "settings/SourceGroupStatusType.h" #include "settings/SourceGroupType.h" +#include "utility/file/FilePathFilter.h" class ProjectSettings; class SourceGroupSettings { public: - static std::string s_keyPrefix; + static const size_t s_version; + static const std::string s_keyPrefix; SourceGroupSettings(const std::string& id, SourceGroupType type, const ProjectSettings* projectSettings); virtual ~SourceGroupSettings(); @@ -46,9 +48,9 @@ public: std::vector getSourcePathsExpandedAndAbsolute() const; void setSourcePaths(const std::vector& sourcePaths); - std::vector getExcludePaths() const; - std::vector getExcludePathsExpandedAndAbsolute() const; - void setExcludePaths(const std::vector& excludePaths); + std::vector getExcludeFilterStrings() const; + std::vector getExcludeFiltersExpandedAndAbsolute() const; + void setExcludeFilterStrings(const std::vector& excludeFilters); std::vector getSourceExtensions() const; void setSourceExtensions(const std::vector& sourceExtensions); @@ -83,7 +85,7 @@ private: std::string m_standard; std::vector m_sourcePaths; - std::vector m_excludePaths; + std::vector m_excludeFilters; std::vector m_sourceExtensions; }; diff --git a/src/lib/utility/file/FileManager.cpp b/src/lib/utility/file/FileManager.cpp index 70a3b01e..91534d81 100644 --- a/src/lib/utility/file/FileManager.cpp +++ b/src/lib/utility/file/FileManager.cpp @@ -4,6 +4,7 @@ #include "utility/file/FileSystem.h" #include "utility/file/FilePath.h" +#include "utility/file/FilePathFilter.h" FileManager::FileManager() { @@ -15,11 +16,11 @@ FileManager::~FileManager() void FileManager::update( const std::vector& sourcePaths, - const std::vector& excludePaths, + const std::vector& excludeFilters, const std::vector& sourceExtensions ){ m_sourcePaths = sourcePaths; - m_excludePaths = makeCanonical(excludePaths); + m_excludeFilters = excludeFilters; m_sourceExtensions = sourceExtensions; m_allSourceFilePaths.clear(); @@ -85,9 +86,9 @@ std::vector FileManager::makeCanonical(const std::vector& fi bool FileManager::isExcluded(const FilePath& filePath) const { - for (const FilePath& path : m_excludePaths) + for (const FilePathFilter& filter : m_excludeFilters) { - if (path == filePath || path.contains(filePath)) + if (filter.isMatching(filePath)) { return true; } diff --git a/src/lib/utility/file/FileManager.h b/src/lib/utility/file/FileManager.h index 73db43fe..b8cc3ec9 100644 --- a/src/lib/utility/file/FileManager.h +++ b/src/lib/utility/file/FileManager.h @@ -7,6 +7,7 @@ #include class FilePath; +class FilePathFilter; class FileManager { @@ -16,7 +17,7 @@ public: void update( const std::vector& sourcePaths, - const std::vector& excludePaths, + const std::vector& excludeFilters, const std::vector& sourceExtensions ); @@ -35,7 +36,7 @@ private: bool isExcluded(const FilePath& filePath) const; std::vector m_sourcePaths; - std::vector m_excludePaths; + std::vector m_excludeFilters; std::vector m_sourceExtensions; std::set m_allSourceFilePaths; diff --git a/src/lib/utility/file/FilePathFilter.cpp b/src/lib/utility/file/FilePathFilter.cpp new file mode 100644 index 00000000..402eb372 --- /dev/null +++ b/src/lib/utility/file/FilePathFilter.cpp @@ -0,0 +1,101 @@ +#include "utility/file/FilePathFilter.h" + +FilePathFilter::FilePathFilter(const std::wstring& filterString) + : m_filterString(filterString) + , m_filterRegex(convertFilterStringToRegex(filterString)) +{ +} + +std::wstring FilePathFilter::wstr() const +{ + return m_filterString; +} + +bool FilePathFilter::isMatching(const FilePath& filePath) const +{ + const std::wstring s = filePath.wstr(); + std::wsmatch match; + return std::regex_match(s, match, m_filterRegex); +} + +bool FilePathFilter::operator<(const FilePathFilter& other) const +{ + return m_filterString.compare(other.m_filterString) < 0; +} + +std::wregex FilePathFilter::convertFilterStringToRegex(const std::wstring& filterString) +{ + std::wstring regexFilterString = filterString; + + { + std::wregex regex(L"[\\\\/]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\\\/]"); + } + + { + std::wregex regex(L"([^\\\\])([^/])([\\]])"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"$1$2[\\]]"); + } + + { + std::wregex regex(L"([\\[])([^\\\\])"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\[]$2"); + } + + { + std::wregex regex(L"[\\(]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\(]"); + } + + { + std::wregex regex(L"[\\)]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\)]"); + } + + { + std::wregex regex(L"[\\{]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\{]"); + } + + { + std::wregex regex(L"[\\}]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\}]"); + } + + { + std::wregex regex(L"[\\+]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\+]"); + } + + { + std::wregex regex(L"[\\-]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\-]"); + } + + { + std::wregex regex(L"[\\$]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\$]"); + } + + { + std::wregex regex(L"[\\.]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\.]"); + } + + { + std::wregex regex(L"[\\^]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[\\^]"); + } + + { + std::wregex regex(L"[\\*][\\*]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L".{0,}"); + } + + { + std::wregex regex(L"[\\*]"); + regexFilterString = std::regex_replace(regexFilterString, regex, L"[^\\\\/]*"); + } + + return std::wregex(regexFilterString); +} diff --git a/src/lib/utility/file/FilePathFilter.h b/src/lib/utility/file/FilePathFilter.h new file mode 100644 index 00000000..b19e7695 --- /dev/null +++ b/src/lib/utility/file/FilePathFilter.h @@ -0,0 +1,27 @@ +#ifndef FILE_PATH_FILTER_H +#define FILE_PATH_FILTER_H + +#include +#include + +#include "utility/file/FilePath.h" + +class FilePathFilter +{ +public: + FilePathFilter(const std::wstring& filterString); + + std::wstring wstr() const; + + bool isMatching(const FilePath& filePath) const; + + bool operator<(const FilePathFilter& other) const; + +private: + static std::wregex convertFilterStringToRegex(const std::wstring& filterString); + + std::wstring m_filterString; + std::wregex m_filterRegex; +}; + +#endif // FILE_PATH_FILTER_H diff --git a/src/lib/utility/file/FileRegister.cpp b/src/lib/utility/file/FileRegister.cpp index c4f2f1bd..103e7c0b 100644 --- a/src/lib/utility/file/FileRegister.cpp +++ b/src/lib/utility/file/FileRegister.cpp @@ -1,17 +1,18 @@ #include "utility/file/FileRegister.h" #include "utility/file/FilePath.h" +#include "utility/file/FilePathFilter.h" FileRegister::FileRegister( const FileRegisterStateData& stateData, const FilePath& currentPath, const std::set& indexedPaths, - const std::set& excludedPaths + const std::set& excludeFilters ) : m_stateData(stateData) , m_currentPath(currentPath) , m_indexedPaths(indexedPaths) - , m_excludedPaths(excludedPaths) + , m_excludeFilters(excludeFilters) , m_hasFilePathCache( [&](const std::wstring& f) { @@ -48,23 +49,12 @@ FileRegister::FileRegister( if (ret) { - for (const FilePath& excluded: m_excludedPaths) + for (const FilePathFilter& excludeFilter: m_excludeFilters) { - if (excluded.isDirectory()) + if (excludeFilter.isMatching(filePath)) { - if (excluded.contains(filePath)) - { - ret = false; - break; - } - } - else - { - if (excluded == filePath) - { - ret = false; - break; - } + ret = false; + break; } } } diff --git a/src/lib/utility/file/FileRegister.h b/src/lib/utility/file/FileRegister.h index 63d6ba1a..a752486e 100644 --- a/src/lib/utility/file/FileRegister.h +++ b/src/lib/utility/file/FileRegister.h @@ -6,6 +6,8 @@ #include "utility/file/FileRegisterStateData.h" #include "utility/UnorderedCache.h" +class FilePathFilter; + class FileRegister { public: @@ -13,7 +15,7 @@ public: const FileRegisterStateData& stateData, const FilePath& currentPath, const std::set& indexedPaths, - const std::set& excludedPaths + const std::set& excludeFilters ); virtual ~FileRegister(); @@ -28,7 +30,7 @@ private: FileRegisterStateData m_stateData; const FilePath& m_currentPath; const std::set m_indexedPaths; - const std::set m_excludedPaths; + const std::set m_excludeFilters; mutable UnorderedCache m_hasFilePathCache; }; diff --git a/src/lib/utility/file/FileSystem.cpp b/src/lib/utility/file/FileSystem.cpp index c7d61b9b..b3598f54 100644 --- a/src/lib/utility/file/FileSystem.cpp +++ b/src/lib/utility/file/FileSystem.cpp @@ -132,10 +132,14 @@ std::vector FileSystem::getFileInfosFromPaths( return files; } +std::set FileSystem::getSymLinkedDirectories(const FilePath& path) +{ + return getSymLinkedDirectories(std::vector{path}); +} + std::set FileSystem::getSymLinkedDirectories(const std::vector& paths) { std::set symlinkDirs; - std::set filePaths; for (const FilePath& path: paths) { diff --git a/src/lib/utility/file/FileSystem.h b/src/lib/utility/file/FileSystem.h index 1fa34a5c..bcfca6d1 100644 --- a/src/lib/utility/file/FileSystem.h +++ b/src/lib/utility/file/FileSystem.h @@ -19,6 +19,7 @@ public: static std::vector getFileInfosFromPaths( const std::vector& paths, const std::vector& fileExtensions, bool followSymLinks = true); + static std::set getSymLinkedDirectories(const FilePath& path); static std::set getSymLinkedDirectories(const std::vector& paths); static unsigned long long getFileByteSize(const FilePath& filePath); diff --git a/src/lib/utility/utility.h b/src/lib/utility/utility.h index e2bf1d7e..12cea58d 100644 --- a/src/lib/utility/utility.h +++ b/src/lib/utility/utility.h @@ -67,6 +67,9 @@ namespace utility template std::vector convert(const std::vector& sourceContainer, std::function conversion); + template + std::vector convert(const std::vector& sourceContainer); + template std::vector toStrings(const std::vector& d); template<> @@ -239,6 +242,17 @@ std::vector utility::convert(const std::vector& sourceCo return targetContainer; } +template +std::vector utility::convert(const std::vector& sourceContainer) +{ + std::vector targetContainer; + for (const SourceType& sourceElement : sourceContainer) + { + targetContainer.push_back(TargetType(sourceElement)); + } + return targetContainer; +} + template std::vector utility::toStrings(const std::vector& d) { diff --git a/src/lib_cxx/data/indexer/IndexerCommandCxx.cpp b/src/lib_cxx/data/indexer/IndexerCommandCxx.cpp index 41c224e8..28fabe7a 100644 --- a/src/lib_cxx/data/indexer/IndexerCommandCxx.cpp +++ b/src/lib_cxx/data/indexer/IndexerCommandCxx.cpp @@ -4,14 +4,14 @@ IndexerCommandCxx::IndexerCommandCxx( const FilePath& sourceFilePath, - const std::set& indexedPaths, - const std::set& excludedPaths, + const std::set& indexedPaths, + const std::set& excludeFilters, const FilePath& workingDirectory, const std::vector& systemHeaderSearchPaths, const std::vector& frameworkSearchPaths, const std::vector& compilerFlags ) - : IndexerCommand(sourceFilePath, indexedPaths, excludedPaths) + : IndexerCommand(sourceFilePath, indexedPaths, excludeFilters) , m_workingDirectory(workingDirectory) , m_systemHeaderSearchPaths(systemHeaderSearchPaths) , m_frameworkSearchPaths(frameworkSearchPaths) diff --git a/src/lib_cxx/data/indexer/IndexerCommandCxx.h b/src/lib_cxx/data/indexer/IndexerCommandCxx.h index 425a0013..a492d760 100644 --- a/src/lib_cxx/data/indexer/IndexerCommandCxx.h +++ b/src/lib_cxx/data/indexer/IndexerCommandCxx.h @@ -15,7 +15,7 @@ public: IndexerCommandCxx( const FilePath& sourceFilePath, const std::set& indexedPaths, - const std::set& excludedPaths, + const std::set& excludeFilters, const FilePath& workingDirectory, const std::vector& systemHeaderSearchPaths, const std::vector& frameworkSearchPaths, diff --git a/src/lib_cxx/data/indexer/IndexerCommandCxxCdb.cpp b/src/lib_cxx/data/indexer/IndexerCommandCxxCdb.cpp index b66605cf..472deb83 100644 --- a/src/lib_cxx/data/indexer/IndexerCommandCxxCdb.cpp +++ b/src/lib_cxx/data/indexer/IndexerCommandCxxCdb.cpp @@ -42,13 +42,13 @@ IndexerCommandType IndexerCommandCxxCdb::getStaticIndexerCommandType() IndexerCommandCxxCdb::IndexerCommandCxxCdb( const FilePath& sourceFilePath, const std::set& indexedPaths, - const std::set& excludedPaths, + const std::set& excludeFilters, const FilePath& workingDirectory, const std::vector& compilerFlags, const std::vector& systemHeaderSearchPaths, const std::vector& frameworkSearchPaths ) - : IndexerCommandCxx(sourceFilePath, indexedPaths, excludedPaths, workingDirectory, systemHeaderSearchPaths, frameworkSearchPaths, compilerFlags) + : IndexerCommandCxx(sourceFilePath, indexedPaths, excludeFilters, workingDirectory, systemHeaderSearchPaths, frameworkSearchPaths, compilerFlags) { } diff --git a/src/lib_cxx/data/indexer/IndexerCommandCxxCdb.h b/src/lib_cxx/data/indexer/IndexerCommandCxxCdb.h index 7f0fd382..a5609edd 100644 --- a/src/lib_cxx/data/indexer/IndexerCommandCxxCdb.h +++ b/src/lib_cxx/data/indexer/IndexerCommandCxxCdb.h @@ -3,6 +3,7 @@ #include "data/indexer/IndexerCommandCxx.h" #include "utility/file/FilePath.h" +#include "utility/file/FilePathFilter.h" namespace clang { @@ -23,7 +24,7 @@ public: IndexerCommandCxxCdb( const FilePath& sourceFilePath, const std::set& indexedPaths, - const std::set& excludedPaths, + const std::set& excludeFilters, const FilePath& workingDirectory, const std::vector& compilerFlags, const std::vector& systemHeaderSearchPaths, diff --git a/src/lib_cxx/data/indexer/IndexerCommandCxxEmpty.cpp b/src/lib_cxx/data/indexer/IndexerCommandCxxEmpty.cpp index b7d19e27..76d24355 100644 --- a/src/lib_cxx/data/indexer/IndexerCommandCxxEmpty.cpp +++ b/src/lib_cxx/data/indexer/IndexerCommandCxxEmpty.cpp @@ -8,14 +8,14 @@ IndexerCommandType IndexerCommandCxxEmpty::getStaticIndexerCommandType() IndexerCommandCxxEmpty::IndexerCommandCxxEmpty( const FilePath& sourceFilePath, const std::set& indexedPaths, - const std::set& excludedPaths, + const std::set& excludeFilters, const FilePath& workingDirectory, const std::string& languageStandard, const std::vector& systemHeaderSearchPaths, const std::vector& frameworkSearchPaths, const std::vector& compilerFlags ) - : IndexerCommandCxx(sourceFilePath, indexedPaths, excludedPaths, workingDirectory, systemHeaderSearchPaths, frameworkSearchPaths, compilerFlags) + : IndexerCommandCxx(sourceFilePath, indexedPaths, excludeFilters, workingDirectory, systemHeaderSearchPaths, frameworkSearchPaths, compilerFlags) , m_languageStandard(languageStandard) { } diff --git a/src/lib_cxx/data/indexer/IndexerCommandCxxEmpty.h b/src/lib_cxx/data/indexer/IndexerCommandCxxEmpty.h index 1ba1f8c2..3e0d88fa 100644 --- a/src/lib_cxx/data/indexer/IndexerCommandCxxEmpty.h +++ b/src/lib_cxx/data/indexer/IndexerCommandCxxEmpty.h @@ -14,7 +14,7 @@ public: IndexerCommandCxxEmpty( const FilePath& sourceFilePath, const std::set& indexedPaths, - const std::set& excludedPaths, + const std::set& excludeFilters, const FilePath& workingDirectory, const std::string& languageStandard, const std::vector& systemHeaderSearchPaths, diff --git a/src/lib_cxx/project/SourceGroupCxxCdb.cpp b/src/lib_cxx/project/SourceGroupCxxCdb.cpp index 300258d0..8e7caa27 100644 --- a/src/lib_cxx/project/SourceGroupCxxCdb.cpp +++ b/src/lib_cxx/project/SourceGroupCxxCdb.cpp @@ -69,7 +69,7 @@ std::vector> SourceGroupCxxCdb::getIndexerComman const std::vector compilerFlags = m_settings->getCompilerFlags(); std::set indexedPaths = getIndexedPaths(); - std::set excludedPaths = getExcludedPaths(); + std::set excludeFilters = getExcludeFilters(); std::vector> indexerCommands; @@ -108,7 +108,7 @@ std::vector> SourceGroupCxxCdb::getIndexerComman indexerCommands.push_back(std::make_shared( sourcePath, indexedPaths, - excludedPaths, + getExcludeFilters(), FilePath(utility::decodeFromUtf8(command.Directory)), utility::concat( utility::convert(command.CommandLine, [](const std::string& arg) { return utility::decodeFromUtf8(arg); }), diff --git a/src/lib_cxx/project/SourceGroupCxxEmpty.cpp b/src/lib_cxx/project/SourceGroupCxxEmpty.cpp index da02f1c8..c67dbcfa 100644 --- a/src/lib_cxx/project/SourceGroupCxxEmpty.cpp +++ b/src/lib_cxx/project/SourceGroupCxxEmpty.cpp @@ -52,7 +52,7 @@ std::vector> SourceGroupCxxEmpty::getIndexerComm utility::append(compilerFlags, m_settings->getCompilerFlags()); std::set indexedPaths = getIndexedPaths(); - std::set excludedPaths = getExcludedPaths(); + std::set excludeFilters = getExcludeFilters(); std::vector> indexerCommands; for (const FilePath& sourcePath: getAllSourceFilePaths()) @@ -62,7 +62,7 @@ std::vector> SourceGroupCxxEmpty::getIndexerComm indexerCommands.push_back(std::make_shared( sourcePath, indexedPaths, - excludedPaths, + excludeFilters, m_settings->getProjectDirectoryPath(), m_settings->getStandard(), systemHeaderSearchPaths, diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentCDBSource.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentCDBSource.cpp index 6624589e..c0e92036 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentCDBSource.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentCDBSource.cpp @@ -33,7 +33,7 @@ void QtProjectWizzardContentCDBSource::load() m_filePaths.clear(); const FilePath projectPath = m_settings->getProjectDirectoryPath(); - std::vector excludePaths = m_settings->getExcludePathsExpandedAndAbsolute(); + const std::vector excludeFilters = m_settings->getExcludeFiltersExpandedAndAbsolute(); if (std::shared_ptr cxxSettings = std::dynamic_pointer_cast(m_settings)) { @@ -44,19 +44,21 @@ void QtProjectWizzardContentCDBSource::load() for (FilePath& path : filePaths) { - bool excluded = false; - for (const FilePath& p : excludePaths) { - if (p == path || p.contains(path)) + bool excluded = false; + for (const FilePathFilter& filter : excludeFilters) { - excluded = true; - break; + if (filter.isMatching(path)) + { + excluded = true; + break; + } } - } - if (excluded) - { - continue; + if (excluded) + { + continue; + } } if (projectPath.exists()) diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp index 726b7c76..02ba2214 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPath.cpp @@ -260,7 +260,7 @@ std::vector QtProjectWizzardContentPathSourceMaven::getFilePaths() con FileManager fileManager; fileManager.update( sourceDirectories, - m_settings->getExcludePathsExpandedAndAbsolute(), + m_settings->getExcludeFiltersExpandedAndAbsolute(), m_settings->getSourceExtensions() ); @@ -391,7 +391,7 @@ std::vector QtProjectWizzardContentPathSourceGradle::getFilePaths() co FileManager fileManager; fileManager.update( sourceDirectories, - m_settings->getExcludePathsExpandedAndAbsolute(), + m_settings->getExcludeFiltersExpandedAndAbsolute(), m_settings->getSourceExtensions() ); diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp index 89fb3b66..9f6c7694 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.cpp @@ -27,11 +27,12 @@ #include "utility/utilityString.h" QtProjectWizzardContentPaths::QtProjectWizzardContentPaths( - std::shared_ptr settings, QtProjectWizzardWindow* window + std::shared_ptr settings, QtProjectWizzardWindow* window, bool checkMissingPaths ) : QtProjectWizzardContent(window) , m_settings(settings) , m_makePathsRelativeToProjectFileLocation(true) + , m_checkMissingPaths(checkMissingPaths) { } @@ -70,56 +71,61 @@ void QtProjectWizzardContentPaths::populate(QGridLayout* layout, int& row) bool QtProjectWizzardContentPaths::check() { - QString missingPaths; - std::vector existingPaths; - - for (const FilePath& path : m_list->getList()) + if (m_checkMissingPaths) { - std::vector expandedPaths(1, path); - if (m_settings) - { - expandedPaths = m_settings->makePathsExpandedAndAbsolute(expandedPaths); - } + QString missingPaths; + std::vector existingPaths; - size_t existingCount = 0; - for (const FilePath& expandedPath : expandedPaths) + for (const FilePath& path : m_list->getList()) { - if (!expandedPath.exists()) + std::vector expandedPaths(1, path); + if (m_settings) { - missingPaths.append(QString::fromStdWString(expandedPath.wstr() + L"\n")); + expandedPaths = m_settings->makePathsExpandedAndAbsolute(expandedPaths); } - else + + size_t existingCount = 0; + for (const FilePath& expandedPath : expandedPaths) { - existingCount++; + if (!expandedPath.exists()) + { + missingPaths.append(QString::fromStdWString(expandedPath.wstr() + L"\n")); + } + else + { + existingCount++; + } + } + + if (!expandedPaths.empty() && expandedPaths.size() == existingCount) + { + existingPaths.push_back(path); } } - if (!expandedPaths.empty() && expandedPaths.size() == existingCount) + if (!missingPaths.isEmpty()) { - existingPaths.push_back(path); + QMessageBox msgBox; + msgBox.setText( + QString( + "Some provided paths do not exist at \"%1\". Do you want to remove them before continuing?" + ).arg(m_titleString) + ); + msgBox.setDetailedText(missingPaths); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + int ret = msgBox.exec(); + + if (ret == QMessageBox::Yes) + { + m_list->setList(existingPaths); + save(); + } + else if (ret == QMessageBox::Cancel) + { + return false; + } } } - - if (!missingPaths.isEmpty()) - { - QMessageBox msgBox; - msgBox.setText(QString("Some provided paths do not exist at \"%1\". Do you want to remove them " - "before continuing?").arg(m_titleString)); - msgBox.setDetailedText(missingPaths); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - int ret = msgBox.exec(); - - if (ret == QMessageBox::Yes) - { - m_list->setList(existingPaths); - save(); - } - else if (ret == QMessageBox::Cancel) - { - return false; - } - } - return true; } @@ -217,7 +223,7 @@ std::vector QtProjectWizzardContentPathsSource::getFilePaths() const FileManager fileManager; fileManager.update( m_settings->getSourcePathsExpandedAndAbsolute(), - m_settings->getExcludePathsExpandedAndAbsolute(), + m_settings->getExcludeFiltersExpandedAndAbsolute(), m_settings->getSourceExtensions() ); @@ -400,7 +406,7 @@ void QtProjectWizzardContentPathsCDBHeader::savedFilesDialog() QtProjectWizzardContentPathsExclude::QtProjectWizzardContentPathsExclude( std::shared_ptr settings, QtProjectWizzardWindow* window ) - : QtProjectWizzardContentPaths(settings, window) + : QtProjectWizzardContentPaths(settings, window, false) { setTitleString("Excluded Files & Directories"); setHelpString( @@ -412,12 +418,12 @@ QtProjectWizzardContentPathsExclude::QtProjectWizzardContentPathsExclude( void QtProjectWizzardContentPathsExclude::load() { - m_list->setList(m_settings->getExcludePaths()); + m_list->setStringList(m_settings->getExcludeFilterStrings()); } void QtProjectWizzardContentPathsExclude::save() { - m_settings->setExcludePaths(m_list->getList()); + m_settings->setExcludeFilterStrings(m_list->getStringList()); } @@ -542,7 +548,7 @@ void QtProjectWizzardContentPathsHeaderSearch::validateIncludesButtonClicked() FileManager fileManager; fileManager.update( m_settings->getSourcePathsExpandedAndAbsolute(), - m_settings->getExcludePathsExpandedAndAbsolute(), + m_settings->getExcludeFiltersExpandedAndAbsolute(), m_settings->getSourceExtensions() ); sourceFilePaths = fileManager.getAllSourceFilePaths(); @@ -605,7 +611,7 @@ void QtProjectWizzardContentPathsHeaderSearch::finishedSelectDetectIncludesRootP FileManager fileManager; fileManager.update( m_settings->getSourcePathsExpandedAndAbsolute(), - m_settings->getExcludePathsExpandedAndAbsolute(), + m_settings->getExcludeFiltersExpandedAndAbsolute(), m_settings->getSourceExtensions() ); sourceFilePaths = fileManager.getAllSourceFilePaths(); diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h index c433a26c..605cfec5 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPaths.h @@ -24,7 +24,7 @@ signals: void showSourceFiles(); public: - QtProjectWizzardContentPaths(std::shared_ptr settings, QtProjectWizzardWindow* window); + QtProjectWizzardContentPaths(std::shared_ptr settings, QtProjectWizzardWindow* window, bool checkMissingPaths = true); // QtSettingsWindow implementation virtual void populate(QGridLayout* layout, int& row) override; @@ -50,6 +50,7 @@ private slots: void detectionClicked(); private: + const bool m_checkMissingPaths; QString m_titleString; QString m_helpString; diff --git a/src/lib_java/data/indexer/IndexerCommandJava.cpp b/src/lib_java/data/indexer/IndexerCommandJava.cpp index d4ef8309..f7e378d6 100644 --- a/src/lib_java/data/indexer/IndexerCommandJava.cpp +++ b/src/lib_java/data/indexer/IndexerCommandJava.cpp @@ -10,11 +10,11 @@ IndexerCommandType IndexerCommandJava::getStaticIndexerCommandType() IndexerCommandJava::IndexerCommandJava( const FilePath& sourceFilePath, const std::set& indexedPaths, - const std::set& excludedPaths, + const std::set& excludeFilters, const std::string& languageStandard, const std::vector& classPath ) - : IndexerCommand(sourceFilePath, indexedPaths, excludedPaths) + : IndexerCommand(sourceFilePath, indexedPaths, excludeFilters) , m_languageStandard(languageStandard) , m_classPath(classPath) { diff --git a/src/lib_java/data/indexer/IndexerCommandJava.h b/src/lib_java/data/indexer/IndexerCommandJava.h index fbf369fb..18d005a9 100644 --- a/src/lib_java/data/indexer/IndexerCommandJava.h +++ b/src/lib_java/data/indexer/IndexerCommandJava.h @@ -16,7 +16,7 @@ public: IndexerCommandJava( const FilePath& sourceFilePath, const std::set& indexedPaths, - const std::set& excludedPaths, + const std::set& excludeFilters, const std::string& languageStandard, const std::vector& classPath); virtual ~IndexerCommandJava(); diff --git a/src/lib_java/project/SourceGroupJava.cpp b/src/lib_java/project/SourceGroupJava.cpp index 5d38577d..122bd782 100644 --- a/src/lib_java/project/SourceGroupJava.cpp +++ b/src/lib_java/project/SourceGroupJava.cpp @@ -37,7 +37,7 @@ std::vector> SourceGroupJava::getIndexerCommands std::vector classPath = getClassPath(); std::set indexedPaths = getIndexedPaths(); - std::set excludedPaths = getExcludedPaths(); + std::set excludeFilters = getExcludeFilters(); std::vector> indexerCommands; for (const FilePath& sourcePath: getAllSourceFilePaths()) @@ -45,7 +45,7 @@ std::vector> SourceGroupJava::getIndexerCommands if (filesToIndex.find(sourcePath) != filesToIndex.end()) { indexerCommands.push_back( - std::make_shared(sourcePath, indexedPaths, excludedPaths, languageStandard, classPath)); + std::make_shared(sourcePath, indexedPaths, excludeFilters, languageStandard, classPath)); } } diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 2fe60fa4..3b00bfa7 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -16,6 +16,7 @@ add_files( CxxParserTestSuite.h CxxTypeNameTestSuite.h FileManagerTestSuite.h + FilePathFilterTestSuite.h FilePathTestSuite.h FileSystemTestSuite.h GeneratorTestSuite.h diff --git a/src/test/CxxIndexSampleProjectsTestSuite.h b/src/test/CxxIndexSampleProjectsTestSuite.h index 1a6d980a..91eae25c 100644 --- a/src/test/CxxIndexSampleProjectsTestSuite.h +++ b/src/test/CxxIndexSampleProjectsTestSuite.h @@ -123,14 +123,14 @@ private: std::shared_ptr parseCode(const FilePath& sourceFilePath, const FilePath& projectDataSrcRoot) { const std::set indexedPaths = { projectDataSrcRoot }; - const std::set excludedPaths = {}; + const std::set excludedFilters = {}; const FilePath workingDirectory(L"."); std::shared_ptr fileRegister = std::make_shared( FileRegisterStateData(), sourceFilePath, indexedPaths, - excludedPaths + excludedFilters ); std::shared_ptr parserClient = std::make_shared(); @@ -140,7 +140,7 @@ private: std::shared_ptr command = std::make_shared( sourceFilePath, indexedPaths, - excludedPaths, + excludedFilters, workingDirectory, "c++1z", utility::concat(std::vector { projectDataSrcRoot }, ApplicationSettings::getInstance()->getHeaderSearchPathsExpanded()), diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index da03e25b..b2f3f281 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -3991,13 +3991,13 @@ public: void test_cxx_parser_parses_multiple_files() { const std::set indexedPaths = { FilePath(L"data/CxxParserTestSuite/") }; - const std::set excludedPaths; + const std::set excludeFilters; const FilePath workingDirectory(L"."); std::shared_ptr indexerCommand = std::make_shared( FilePath(L"data/CxxParserTestSuite/code.cpp"), indexedPaths, - excludedPaths, + excludeFilters, workingDirectory, "c++1z", std::vector(), diff --git a/src/test/FileManagerTestSuite.h b/src/test/FileManagerTestSuite.h index 4983318b..7b0eb6ea 100644 --- a/src/test/FileManagerTestSuite.h +++ b/src/test/FileManagerTestSuite.h @@ -14,7 +14,7 @@ public: sourcePaths.push_back(FilePath(L"./data/FileManagerTestSuite/src/")); sourcePaths.push_back(FilePath(L"./data/FileManagerTestSuite/include/")); std::vector headerPaths; - std::vector excludePaths; + std::vector excludeFilters; std::vector filePaths = FileSystem::getFilePathsFromDirectory(FilePath(L"./data/FileManagerTestSuite/src/")); TS_ASSERT_EQUALS(filePaths.size(), 3); @@ -27,7 +27,7 @@ public: TS_ASSERT_EQUALS(sourceExtensions.size(), 3); FileManager fm; - fm.update(sourcePaths, excludePaths, sourceExtensions); + fm.update(sourcePaths, excludeFilters, sourceExtensions); std::vector foundSourcePaths = utility::toVector(fm.getAllSourceFilePaths()); TS_ASSERT_EQUALS(foundSourcePaths.size(), 3); diff --git a/src/test/FilePathFilterTestSuite.h b/src/test/FilePathFilterTestSuite.h new file mode 100644 index 00000000..4ac0fdaf --- /dev/null +++ b/src/test/FilePathFilterTestSuite.h @@ -0,0 +1,127 @@ +#include "cxxtest/TestSuite.h" + +#include "utility/file/FilePathFilter.h" + +class FilePathFilterTestSuite: public CxxTest::TestSuite +{ +public: + void test_file_path_filter_finds_exact_match() + { + FilePathFilter filter(L"test.h"); + + TS_ASSERT(filter.isMatching(FilePath(L"test.h"))); + } + + void test_file_path_filter_finds_match_with_single_asterisk_in_same_level() + { + FilePathFilter filter(L"*test.*"); + + TS_ASSERT(filter.isMatching(FilePath(L"this_is_a_test.h"))); + } + + void test_file_path_filter_finds_match_with_single_asterisk_in_different_level() + { + FilePathFilter filter(L"*/this_is_a_test.h"); + + TS_ASSERT(filter.isMatching(FilePath(L"folder/this_is_a_test.h"))); + } + + void test_file_path_filter_does_not_find_match_with_single_asterisk_in_different_level() + { + FilePathFilter filter(L"*/test.h"); + + TS_ASSERT(!filter.isMatching(FilePath(L"test.h"))); + } + + void test_file_path_filter_finds_match_with_multiple_asterisk_in_same_level() + { + FilePathFilter filter(L"**test.h"); + + TS_ASSERT(filter.isMatching(FilePath(L"folder/this_is_a_test.h"))); + } + + void test_file_path_filter_finds_match_with_multiple_asterisk_in_different_level() + { + FilePathFilter filter(L"root/**/test.h"); + + TS_ASSERT(filter.isMatching(FilePath(L"root/folder1/folder2/test.h"))); + } + + void test_file_path_filter_does_not_find_match_with_multiple_asterisk_in_different_level() + { + FilePathFilter filter(L"**/test.h"); + + TS_ASSERT(!filter.isMatching(FilePath(L"folder/this_is_a_test.h"))); + } + + void test_file_path_filter_escapes_dot_character() + { + FilePathFilter filter(L"test.h"); + + TS_ASSERT(!filter.isMatching(FilePath(L"testyh"))); + } + + void test_file_path_filter_escapes_plus_character() + { + TS_ASSERT(FilePathFilter(L"folder/test+.h").isMatching(FilePath(L"folder/test+.h"))); + } + + void test_file_path_filter_escapes_minus_character() + { + TS_ASSERT(FilePathFilter(L"folder/test[-].h").isMatching(FilePath(L"folder/test[-].h"))); + } + + void test_file_path_filter_escapes_dollar_character() + { + TS_ASSERT(FilePathFilter(L"folder/test$.h").isMatching(FilePath(L"folder/test$.h"))); + } + + void test_file_path_filter_escapes_circumflex_character() + { + TS_ASSERT(FilePathFilter(L"folder/test^.h").isMatching(FilePath(L"folder/test^.h"))); + } + + void test_file_path_filter_escapes_open_round_brace_character() + { + TS_ASSERT(FilePathFilter(L"folder/test(.h").isMatching(FilePath(L"folder/test(.h"))); + } + + void test_file_path_filter_escapes_close_round_brace_character() + { + TS_ASSERT(FilePathFilter(L"folder\\test).h").isMatching(FilePath(L"folder/test).h"))); + } + + void test_file_path_filter_escapes_open_curly_brace_character() + { + TS_ASSERT(FilePathFilter(L"folder/test{.h").isMatching(FilePath(L"folder/test{.h"))); + } + + void test_file_path_filter_escapes_close_curly_brace_character() + { + TS_ASSERT(FilePathFilter(L"folder/test}.h").isMatching(FilePath(L"folder/test}.h"))); + } + + void test_file_path_filter_escapes_open_squared_brace_character() + { + TS_ASSERT(FilePathFilter(L"folder/test[.h").isMatching(FilePath(L"folder/test[.h"))); + } + + void test_file_path_filter_escapes_close_squared_brace_character() + { + TS_ASSERT(FilePathFilter(L"folder\\test].h").isMatching(FilePath(L"folder/test].h"))); + } + + void test_file_path_filter_finds_backslash_if_slash_was_provided() + { + FilePathFilter filter(L"folder/test.h"); + + TS_ASSERT(filter.isMatching(FilePath(L"folder\\test.h"))); + } + + void test_file_path_filter_finds_slash_if_backslash_was_provided() + { + FilePathFilter filter(L"folder\\test.h"); + + TS_ASSERT(filter.isMatching(FilePath(L"folder/test.h"))); + } +}; diff --git a/src/test/JavaIndexSampleProjectsTestSuite.h b/src/test/JavaIndexSampleProjectsTestSuite.h index c3d07046..d660bea6 100644 --- a/src/test/JavaIndexSampleProjectsTestSuite.h +++ b/src/test/JavaIndexSampleProjectsTestSuite.h @@ -248,19 +248,19 @@ private: std::shared_ptr parseCode(const FilePath& sourceFilePath, const FilePath& projectDataSrcRoot, const std::vector& classpath) { std::set indexedPaths = { projectDataSrcRoot }; - std::set excludedPaths = { }; + std::set excludeFilters = { }; std::shared_ptr fileRegister = std::make_shared( FileRegisterStateData(), sourceFilePath, indexedPaths, - excludedPaths + excludeFilters ); std::shared_ptr parserClient = std::make_shared(); JavaParser parser(parserClient, fileRegister); - std::shared_ptr command = std::make_shared(sourceFilePath, indexedPaths, excludedPaths, "8", classpath); + std::shared_ptr command = std::make_shared(sourceFilePath, indexedPaths, excludeFilters, "8", classpath); parser.buildIndex(command); diff --git a/src/test/helper/TestFileRegister.cpp b/src/test/helper/TestFileRegister.cpp index c6ef27d5..b4c949a4 100644 --- a/src/test/helper/TestFileRegister.cpp +++ b/src/test/helper/TestFileRegister.cpp @@ -1,7 +1,9 @@ #include "TestFileRegister.h" +#include "utility/file/FilePathFilter.h" + TestFileRegister::TestFileRegister() - : FileRegister(FileRegisterStateData(), FilePath(), std::set(), std::set()) + : FileRegister(FileRegisterStateData(), FilePath(), std::set(), { FilePathFilter(L"") }) { }