diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d608c90..b794d398 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,7 +190,6 @@ target_sources(ccls PRIVATE src/indexer.cc src/log.cc src/lsp.cc - src/match.cc src/message_handler.cc src/pipeline.cc src/platform_posix.cc diff --git a/src/clang_complete.cc b/src/clang_complete.cc index f725d98e..8bb23b1a 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -6,7 +6,6 @@ #include "clang_tu.hh" #include "filesystem.hh" #include "log.hh" -#include "match.hh" #include "platform.hh" #include @@ -574,7 +573,7 @@ void CompletionManager::DiagnosticsUpdate(const std::string &path, int debounce) { static GroupMatch match(g_config->diagnostics.whitelist, g_config->diagnostics.blacklist); - if (!match.IsMatch(path)) + if (!match.Matches(path)) return; int64_t now = chrono::duration_cast( chrono::high_resolution_clock::now().time_since_epoch()) diff --git a/src/include_complete.cc b/src/include_complete.cc index 0c17809e..a07d66d3 100644 --- a/src/include_complete.cc +++ b/src/include_complete.cc @@ -4,7 +4,6 @@ #include "include_complete.hh" #include "filesystem.hh" -#include "match.hh" #include "platform.hh" #include "project.hh" @@ -150,7 +149,7 @@ void IncludeComplete::AddFile(const std::string &path) { ok = true; if (!ok) return; - if (match_ && !match_->IsMatch(path)) + if (match_ && !match_->Matches(path)) return; std::string trimmed_path = path; @@ -167,7 +166,7 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory, bool use_angle_brackets) { directory = NormalizePath(directory); EnsureEndsInSlash(directory); - if (match_ && !match_->IsMatch(directory)) + if (match_ && !match_->Matches(directory)) return; bool include_cpp = directory.find("include/c++") != std::string::npos; @@ -181,7 +180,7 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory, ok = true; if (!ok) return; - if (match_ && !match_->IsMatch(directory + path)) + if (match_ && !match_->Matches(directory + path)) return; CompletionCandidate candidate; diff --git a/src/indexer.cc b/src/indexer.cc index bc10732f..94286959 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -6,7 +6,6 @@ #include "clang_complete.hh" #include "clang_tu.hh" #include "log.hh" -#include "match.hh" #include "pipeline.hh" #include "platform.hh" #include "serializer.hh" @@ -85,7 +84,7 @@ struct IndexParam { bool UseMultiVersion(const FileEntry &FE) { auto it = UID2multi.try_emplace(FE.getUniqueID()); if (it.second) - it.first->second = multiVersionMatcher->IsMatch(PathFromFileEntry(FE)); + it.first->second = multiVersionMatcher->Matches(PathFromFileEntry(FE)); return it.first->second; } }; diff --git a/src/match.cc b/src/match.cc deleted file mode 100644 index 07b75d08..00000000 --- a/src/match.cc +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2017-2018 ccls Authors -// SPDX-License-Identifier: Apache-2.0 - -#include "match.hh" - -#include "message_handler.hh" -#include "pipeline.hh" - -namespace ccls { -std::optional Matcher::Create(const std::string &search) { - try { - Matcher m; - m.regex_string = search; - m.regex = std::regex(search, std::regex_constants::ECMAScript | - std::regex_constants::icase | - std::regex_constants::optimize - // std::regex_constants::nosubs - ); - return m; - } catch (const std::exception &e) { - ShowMessageParam params; - params.type = MessageType::Error; - params.message = - "failed to parse EMCAScript regex " + search + " : " + e.what(); - pipeline::Notify(window_showMessage, params); - return std::nullopt; - } -} - -bool Matcher::IsMatch(const std::string &value) const { - // std::smatch match; - // return std::regex_match(value, match, regex); - return std::regex_search(value, regex, std::regex_constants::match_any); -} - -GroupMatch::GroupMatch(const std::vector &whitelist, - const std::vector &blacklist) { - for (const std::string &entry : whitelist) { - std::optional m = Matcher::Create(entry); - if (m) - this->whitelist.push_back(*m); - } - for (const std::string &entry : blacklist) { - std::optional m = Matcher::Create(entry); - if (m) - this->blacklist.push_back(*m); - } -} - -bool GroupMatch::IsMatch(const std::string &value, - std::string *match_failure_reason) const { - for (const Matcher &m : whitelist) - if (m.IsMatch(value)) - return true; - - for (const Matcher &m : blacklist) - if (m.IsMatch(value)) { - if (match_failure_reason) - *match_failure_reason = "blacklist \"" + m.regex_string + "\""; - return false; - } - - return true; -} -} // namespace ccls diff --git a/src/match.hh b/src/match.hh deleted file mode 100644 index e2d205c1..00000000 --- a/src/match.hh +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017-2018 ccls Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include -#include -#include - -namespace ccls { -struct Matcher { - static std::optional Create(const std::string &search); - - bool IsMatch(const std::string &value) const; - - std::string regex_string; - std::regex regex; -}; - -// Check multiple |Matcher| instances at the same time. -struct GroupMatch { - GroupMatch(const std::vector &whitelist, - const std::vector &blacklist); - - bool IsMatch(const std::string &value, - std::string *match_failure_reason = nullptr) const; - - std::vector whitelist; - std::vector blacklist; -}; -} // namespace ccls diff --git a/src/message_handler.cc b/src/message_handler.cc index 48bd432d..4c093f4a 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -4,7 +4,6 @@ #include "message_handler.hh" #include "log.hh" -#include "match.hh" #include "pipeline.hh" #include "project.hh" #include "query_utils.hh" @@ -263,7 +262,7 @@ void EmitSemanticHighlight(DB *db, WorkingFile *wfile, QueryFile &file) { g_config->highlight.blacklist); assert(file.def); if (wfile->buffer_content.size() > g_config->highlight.largeFileSize || - !match.IsMatch(file.def->path)) + !match.Matches(file.def->path)) return; // Group symbols together. diff --git a/src/messages/ccls_reload.cc b/src/messages/ccls_reload.cc index 944f9a06..13db9bf8 100644 --- a/src/messages/ccls_reload.cc +++ b/src/messages/ccls_reload.cc @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 #include "clang_complete.hh" -#include "match.hh" #include "message_handler.hh" #include "pipeline.hh" #include "project.hh" diff --git a/src/pipeline.cc b/src/pipeline.cc index 0ef0af0e..0aeaa8d6 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -8,7 +8,6 @@ #include "include_complete.hh" #include "log.hh" #include "lsp.hh" -#include "match.hh" #include "message_handler.hh" #include "pipeline.hh" #include "platform.hh" @@ -187,7 +186,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, return false; } - if (!matcher.IsMatch(request.path)) { + if (!matcher.Matches(request.path)) { LOG_IF_S(INFO, loud) << "skip " << request.path; return false; } @@ -309,7 +308,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, for (std::unique_ptr &curr : indexes) { std::string path = curr->path; - if (!matcher.IsMatch(path)) { + if (!matcher.Matches(path)) { LOG_IF_S(INFO, loud) << "skip index for " << path; continue; } diff --git a/src/project.cc b/src/project.cc index ab09c1b5..f1496418 100644 --- a/src/project.cc +++ b/src/project.cc @@ -6,7 +6,6 @@ #include "clang_tu.hh" // llvm::vfs #include "filesystem.hh" #include "log.hh" -#include "match.hh" #include "pipeline.hh" #include "platform.hh" #include "serializers/json.hh" @@ -485,8 +484,8 @@ void Project::Index(WorkingFiles *wfiles, RequestId id) { int i = 0; for (const Project::Entry &entry : folder.entries) { std::string reason; - if (match.IsMatch(entry.filename, &reason) && - match_i.IsMatch(entry.filename, &reason)) { + if (match.Matches(entry.filename, &reason) && + match_i.Matches(entry.filename, &reason)) { bool interactive = wfiles->GetFileByFilename(entry.filename) != nullptr; pipeline::Index( diff --git a/src/utils.cc b/src/utils.cc index 369d5bb3..6dc288b1 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -4,6 +4,8 @@ #include "utils.hh" #include "log.hh" +#include "message_handler.hh" +#include "pipeline.hh" #include "platform.hh" #include @@ -18,10 +20,67 @@ using namespace llvm; #include #include #include +#include #include #include namespace ccls { +struct Matcher::Impl { + std::regex regex; +}; + +Matcher::Matcher(const std::string &pattern) + : impl(std::make_unique()), pattern(pattern) { + impl->regex = std::regex(pattern, std::regex_constants::ECMAScript | + std::regex_constants::icase | + std::regex_constants::optimize); +} + +Matcher::~Matcher() {} + +bool Matcher::Matches(const std::string &text) const { + return std::regex_search(text, impl->regex, std::regex_constants::match_any); +} + +GroupMatch::GroupMatch(const std::vector &whitelist, + const std::vector &blacklist) { + auto err = [](const std::string &pattern, const char *what) { + ShowMessageParam params; + params.type = MessageType::Error; + params.message = + "failed to parse EMCAScript regex " + pattern + " : " + what; + pipeline::Notify(window_showMessage, params); + }; + for (const std::string &pattern : whitelist) { + try { + this->whitelist.emplace_back(pattern); + } catch (const std::exception &e) { + err(pattern, e.what()); + } + } + for (const std::string &pattern : blacklist) { + try { + this->blacklist.emplace_back(pattern); + } catch (const std::exception &e) { + err(pattern, e.what()); + } + } +} + +bool GroupMatch::Matches(const std::string &text, + std::string *blacklist_pattern) const { + for (const Matcher &m : whitelist) + if (m.Matches(text)) + return true; + for (const Matcher &m : blacklist) + if (m.Matches(text)) { + if (blacklist_pattern) + *blacklist_pattern = m.pattern; + return false; + } + return true; +} + uint64_t HashUsr(llvm::StringRef s) { union { uint64_t ret; diff --git a/src/utils.hh b/src/utils.hh index db4e9493..3a5cdbd1 100644 --- a/src/utils.hh +++ b/src/utils.hh @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -15,6 +16,26 @@ class StringRef; } namespace ccls { +struct Matcher { + struct Impl; + std::unique_ptr impl; + std::string pattern; + + Matcher(const std::string &pattern); // throw + Matcher(Matcher&&) = default; + ~Matcher(); + bool Matches(const std::string &text) const; +}; + +struct GroupMatch { + std::vector whitelist, blacklist; + + GroupMatch(const std::vector &whitelist, + const std::vector &blacklist); + bool Matches(const std::string &text, + std::string *blacklist_pattern = nullptr) const; +}; + uint64_t HashUsr(llvm::StringRef s); std::string LowerPathIfInsensitive(const std::string &path);